From 9c73ef7a5ac10acd6a50d5d52bd721fc2faa5919 Mon Sep 17 00:00:00 2001 From: Kim van der Riet Date: Thu, 28 Feb 2013 16:14:30 +0000 Subject: Update from trunk r1375509 through r1450773 git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1451244 13f79535-47bb-0310-9956-ffa450edef68 --- java/.gitignore | 1 + java/amqp-1-0-client-jms/build.xml | 3 + java/amqp-1-0-client-jms/example/build.xml | 28 + java/amqp-1-0-client-jms/resources/LICENSE | 204 ++ java/amqp-1-0-client-jms/resources/NOTICE | 5 + java/amqp-1-0-client-jms/resources/README.txt | 7 + .../amqp_1_0/jms/impl/ConnectionFactoryImpl.java | 79 +- .../qpid/amqp_1_0/jms/impl/ConnectionImpl.java | 172 +- .../qpid/amqp_1_0/jms/impl/DecodedDestination.java | 47 + .../amqp_1_0/jms/impl/MessageConsumerImpl.java | 6 +- .../apache/qpid/amqp_1_0/jms/impl/MessageImpl.java | 183 +- .../amqp_1_0/jms/impl/MessageProducerImpl.java | 5 +- .../qpid/amqp_1_0/jms/impl/ObjectMessageImpl.java | 20 +- .../qpid/amqp_1_0/jms/impl/QueueBrowserImpl.java | 151 +- .../qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java | 2 +- .../apache/qpid/amqp_1_0/jms/impl/SessionImpl.java | 20 +- .../amqp_1_0/jms/impl/TopicSubscriberImpl.java | 2 +- .../jndi/PropertiesFileInitialContextFactory.java | 3 + java/amqp-1-0-client/build.xml | 3 + java/amqp-1-0-client/example/build.xml | 28 + .../org/apache/qpid/amqp_1_0/client/Command.java | 43 + .../java/org/apache/qpid/amqp_1_0/client/Demo.java | 407 ++++ .../java/org/apache/qpid/amqp_1_0/client/Dump.java | 136 ++ .../apache/qpid/amqp_1_0/client/Filereceiver.java | 347 ++++ .../apache/qpid/amqp_1_0/client/Filesender.java | 296 +++ .../org/apache/qpid/amqp_1_0/client/Receive.java | 246 +++ .../org/apache/qpid/amqp_1_0/client/Request.java | 249 +++ .../org/apache/qpid/amqp_1_0/client/Respond.java | 347 ++++ .../java/org/apache/qpid/amqp_1_0/client/Send.java | 244 +++ .../java/org/apache/qpid/amqp_1_0/client/Util.java | 529 +++++ java/amqp-1-0-client/resources/LICENSE | 204 ++ java/amqp-1-0-client/resources/NOTICE | 5 + java/amqp-1-0-client/resources/README.txt | 7 + .../org/apache/qpid/amqp_1_0/client/Command.java | 43 - .../apache/qpid/amqp_1_0/client/Connection.java | 115 +- .../java/org/apache/qpid/amqp_1_0/client/Demo.java | 407 ---- .../java/org/apache/qpid/amqp_1_0/client/Dump.java | 136 -- .../apache/qpid/amqp_1_0/client/Filereceiver.java | 347 ---- .../apache/qpid/amqp_1_0/client/Filesender.java | 296 --- .../org/apache/qpid/amqp_1_0/client/ReadBytes.java | 77 - .../org/apache/qpid/amqp_1_0/client/Receive.java | 246 --- .../org/apache/qpid/amqp_1_0/client/Receiver.java | 35 +- .../org/apache/qpid/amqp_1_0/client/Request.java | 249 --- .../org/apache/qpid/amqp_1_0/client/Respond.java | 347 ---- .../java/org/apache/qpid/amqp_1_0/client/Send.java | 244 --- .../org/apache/qpid/amqp_1_0/client/SendBytes.java | 331 ---- .../java/org/apache/qpid/amqp_1_0/client/Util.java | 529 ----- java/amqp-1-0-common/resources/LICENSE | 204 ++ java/amqp-1-0-common/resources/NOTICE | 5 + java/amqp-1-0-common/resources/README.txt | 7 + .../apache/qpid/amqp_1_0/codec/FrameWriter.java | 27 +- .../org/apache/qpid/amqp_1_0/framing/AMQFrame.java | 8 + .../qpid/amqp_1_0/framing/ConnectionHandler.java | 23 +- .../amqp_1_0/transport/ConnectionEndpoint.java | 13 + .../apache/qpid/amqp_1_0/transport/Delivery.java | 4 + .../amqp_1_0/transport/ReceivingLinkEndpoint.java | 24 +- java/bdbstore/bin/backup.sh | 5 +- java/bdbstore/build.xml | 17 +- java/bdbstore/jmx/MANIFEST.MF | 20 - java/bdbstore/jmx/build.xml | 6 +- .../jmx/BDBHAMessageStoreManagerMBean.java | 3 +- .../jmx/BDBHAMessageStoreManagerMBeanProvider.java | 11 +- .../org.apache.qpid.server.jmx.MBeanProvider | 18 + .../store/berkeleydb/HAClusterManagementTest.java | 36 +- .../store/berkeleydb/HAClusterTwoNodeTest.java | 12 +- .../jmx/BDBHAMessageStoreManagerMBeanTest.java | 3 +- .../store/berkeleydb/AbstractBDBMessageStore.java | 169 +- .../server/store/berkeleydb/BDBHAMessageStore.java | 4 +- .../store/berkeleydb/BDBHAMessageStoreFactory.java | 41 + .../server/store/berkeleydb/BDBMessageStore.java | 4 +- .../store/berkeleydb/BDBMessageStoreFactory.java | 41 + .../store/berkeleydb/CommitThreadWrapper.java | 31 +- ...rg.apache.qpid.server.store.MessageStoreFactory | 20 + .../server/store/berkeleydb/BDBBackupTest.java | 2 +- .../store/berkeleydb/BDBHAMessageStoreTest.java | 74 +- .../store/berkeleydb/BDBMessageStoreTest.java | 2 +- .../berkeleydb/BDBStoreUpgradeTestPreparer.java | 62 +- .../server/store/berkeleydb/BDBUpgradeTest.java | 127 +- .../store/berkeleydb/HAClusterBlackboxTest.java | 6 +- .../store/berkeleydb/HATestClusterCreator.java | 36 +- .../store/berkeleydb/MessageStoreCreatorTest.java | 44 + .../upgrade/AbstractUpgradeTestCase.java | 39 +- .../berkeleydb/upgrade/UpgradeFrom4to5Test.java | 47 +- .../berkeleydb/upgrade/UpgradeFrom5To6Test.java | 63 +- .../upgrade/bdbstore-v4/test-store/00000000.jdb | Bin 1361990 -> 1366145 bytes .../upgrade/bdbstore-v5/test-store/00000000.jdb | Bin 1361990 -> 1366145 bytes .../upgrade/bdbstore-v5/test-store/00000001.jdb | Bin 1333643 -> 1336563 bytes java/broker-plugins/access-control/MANIFEST.MF | 41 - java/broker-plugins/access-control/build.xml | 6 +- .../access/config/AbstractConfiguration.java | 7 +- .../server/security/access/config/AclAction.java | 102 + .../security/access/config/AclRulePredicates.java | 102 + .../qpid/server/security/access/config/Action.java | 114 +- .../security/access/config/ClientAction.java | 88 + .../security/access/config/ConfigurationFile.java | 12 +- .../security/access/config/PlainConfiguration.java | 184 +- .../qpid/server/security/access/config/Rule.java | 44 +- .../server/security/access/config/RuleSet.java | 113 +- .../firewall/AccessControlFirewallException.java | 47 + .../security/access/firewall/FirewallRule.java | 26 + .../access/firewall/FirewallRuleFactory.java | 33 + .../access/firewall/HostnameFirewallRule.java | 156 ++ .../security/access/firewall/InetNetwork.java | 177 ++ .../access/firewall/NetworkFirewallRule.java | 117 ++ .../logging/AccessControl_logmessages.properties | 2 +- .../security/access/plugins/AccessControl.java | 116 -- .../access/plugins/AccessControlActivator.java | 41 - .../access/plugins/AccessControlConfiguration.java | 83 - .../access/plugins/DefaultAccessControl.java | 122 ++ .../plugins/DefaultAccessControlFactory.java | 59 + ....apache.qpid.server.plugin.AccessControlFactory | 19 + .../security/access/config/AclActionTest.java | 66 + .../access/config/AclRulePredicatesTest.java | 87 + .../server/security/access/config/ActionTest.java | 95 + .../security/access/config/ClientActionTest.java | 79 + .../access/config/PlainConfigurationTest.java | 463 +++++ .../server/security/access/config/RuleTest.java | 53 + .../access/firewall/HostnameFirewallRuleTest.java | 99 + .../access/firewall/NetworkFirewallRuleTest.java | 115 ++ .../security/access/plugins/AccessControlTest.java | 355 ---- .../plugins/DefaultAccessControlFactoryTest.java | 69 + .../access/plugins/DefaultAccessControlTest.java | 368 ++++ .../access/plugins/PlainConfigurationTest.java | 394 ---- .../security/access/plugins/RuleSetTest.java | 92 +- java/broker-plugins/firewall/MANIFEST.MF | 34 - java/broker-plugins/firewall/build.xml | 34 - .../security/access/config/FirewallException.java | 46 - .../security/access/config/FirewallRule.java | 136 -- .../server/security/access/plugins/Firewall.java | 137 -- .../security/access/plugins/FirewallActivator.java | 41 - .../access/plugins/FirewallConfiguration.java | 103 - .../security/access/FirewallConfigurationTest.java | 322 --- .../server/security/access/FirewallPluginTest.java | 294 --- java/broker-plugins/management-http/MANIFEST.MF | 70 - java/broker-plugins/management-http/build.xml | 51 +- .../server/management/plugin/HttpManagement.java | 416 ++++ .../management/plugin/HttpManagementFactory.java | 41 + .../qpid/server/management/plugin/Management.java | 248 --- .../management/plugin/ManagementActivator.java | 73 - .../management/plugin/ManagementConfiguration.java | 77 - .../plugin/servlet/DefinedFileServlet.java | 2 +- .../management/plugin/servlet/FileServlet.java | 5 +- .../plugin/servlet/api/ExchangesServlet.java | 208 -- .../plugin/servlet/api/VhostsServlet.java | 118 -- .../plugin/servlet/rest/AbstractServlet.java | 447 ++++- .../plugin/servlet/rest/LogRecordsServlet.java | 15 +- .../plugin/servlet/rest/LogoutServlet.java | 65 + .../plugin/servlet/rest/MessageContentServlet.java | 8 +- .../plugin/servlet/rest/MessageServlet.java | 41 +- .../plugin/servlet/rest/RestServlet.java | 38 +- .../plugin/servlet/rest/SaslServlet.java | 95 +- .../plugin/servlet/rest/StructureServlet.java | 9 +- .../plugin/session/LoginLogoutReporter.java | 103 + ...showPrincipalDatabaseAuthenticationManager.html | 2 - .../main/java/resources/group/addGroupMember.html | 37 + .../src/main/java/resources/group/showGroup.html | 30 + .../java/resources/groupprovider/addGroup.html | 38 + .../groupprovider/showFileGroupManager.html | 28 + .../src/main/java/resources/index.html | 90 + .../java/resources/js/qpid/authorization/sasl.js | 59 +- .../src/main/java/resources/js/qpid/common/util.js | 7 +- .../java/resources/js/qpid/management/Exchange.js | 2 +- .../resources/js/qpid/management/GroupProvider.js | 109 + .../resources/js/qpid/management/VirtualHost.js | 4 +- .../resources/js/qpid/management/controller.js | 8 +- .../resources/js/qpid/management/group/Group.js | 204 ++ .../js/qpid/management/group/addGroupMember.js | 108 + .../management/groupprovider/FileGroupManager.js | 251 +++ .../java/resources/js/qpid/management/treeView.js | 6 +- .../src/main/java/resources/management.html | 92 - .../src/main/java/resources/showGroupProvider.html | 25 + .../org.apache.qpid.server.plugin.PluginFactory | 19 + .../plugin/HttpManagementFactoryTest.java | 61 + .../management/plugin/servlet/rest/Asserts.java | 249 --- .../rest/AuthenticationProviderRestTest.java | 73 - .../plugin/servlet/rest/BindingRestTest.java | 129 -- .../plugin/servlet/rest/BrokerRestHttpsTest.java | 86 - .../plugin/servlet/rest/BrokerRestTest.java | 118 -- .../plugin/servlet/rest/ConnectionRestTest.java | 213 -- .../plugin/servlet/rest/ExchangeRestTest.java | 87 - .../plugin/servlet/rest/LogRecordsRestTest.java | 42 - .../plugin/servlet/rest/MessagesRestTest.java | 354 ---- .../plugin/servlet/rest/PortRestTest.java | 61 - .../plugin/servlet/rest/QpidRestTestCase.java | 245 --- .../plugin/servlet/rest/QueueRestTest.java | 225 --- .../plugin/servlet/rest/SaslRestTest.java | 42 - .../plugin/servlet/rest/StructureRestTest.java | 115 -- .../plugin/servlet/rest/UserRestTest.java | 112 -- .../plugin/servlet/rest/VirtualHostRestTest.java | 434 ---- .../plugin/session/LoginLogoutReporterTest.java | 74 + java/broker-plugins/management-jmx/MANIFEST.MF | 66 - java/broker-plugins/management-jmx/build.xml | 20 +- .../server/jmx/CustomRMIServerSocketFactory.java | 68 + .../org/apache/qpid/server/jmx/JMXActivator.java | 136 -- .../apache/qpid/server/jmx/JMXConfiguration.java | 76 - .../qpid/server/jmx/JMXManagedObjectRegistry.java | 407 ++-- .../org/apache/qpid/server/jmx/JMXManagement.java | 343 ++++ .../qpid/server/jmx/JMXManagementFactory.java | 49 + .../org/apache/qpid/server/jmx/JMXService.java | 193 -- .../server/jmx/MBeanInvocationHandlerImpl.java | 101 +- .../org/apache/qpid/server/jmx/MBeanProvider.java | 5 +- .../server/jmx/ManagementLogonLogoffReporter.java | 95 + .../apache/qpid/server/jmx/UsernameAccessor.java | 26 + .../server/jmx/UsernameCachingRMIJRMPServer.java | 100 + .../jmx/mbeans/ConfigurationManagementMBean.java | 56 - .../server/jmx/mbeans/LoggingManagementMBean.java | 53 +- .../apache/qpid/server/jmx/mbeans/QueueMBean.java | 5 +- .../qpid/server/jmx/mbeans/VirtualHostMBean.java | 66 +- .../server/jmx/mbeans/VirtualHostManagerMBean.java | 5 +- .../org.apache.qpid.server.plugin.PluginFactory | 19 + .../qpid/server/jmx/JMXManagementFactoryTest.java | 60 + .../qpid/server/jmx/ManagementLogActorTest.java | 170 -- .../jmx/ManagementLogonLogoffReporterTest.java | 101 + .../jmx/mbeans/LoggingManagementMBeanTest.java | 6 +- .../management/jmx/BrokerManagementTest.java | 124 -- .../management/jmx/ConnectionManagementTest.java | 283 --- .../management/jmx/LoggingManagementTest.java | 149 -- .../management/jmx/ManagementActorLoggingTest.java | 480 ----- .../management/jmx/ManagementLoggingTest.java | 317 --- .../management/jmx/QueueManagementTest.java | 696 ------- .../systest/management/jmx/StatisticsTest.java | 204 -- .../systest/management/jmx/UserManagementTest.java | 251 --- .../UserManagementWithBase64MD5PasswordsTest.java | 39 - java/broker/bin/qpid-server | 4 +- java/broker/bin/qpid-server.bat | 4 +- java/broker/build.xml | 30 +- java/broker/etc/broker_example.acl | 94 +- java/broker/etc/config.xml | 106 - java/broker/etc/groups | 29 + java/broker/etc/log4j.xml | 23 +- java/broker/src/main/java/broker.bnd | 2 +- .../java/org/apache/qpid/qmf/CompletionCode.java | 36 - .../org/apache/qpid/qmf/ManagementExchange.java | 586 ------ .../apache/qpid/qmf/QMFBrokerRequestCommand.java | 82 - .../apache/qpid/qmf/QMFBrokerResponseCommand.java | 45 - .../main/java/org/apache/qpid/qmf/QMFClass.java | 156 -- .../apache/qpid/qmf/QMFClassIndicationCommand.java | 48 - .../org/apache/qpid/qmf/QMFClassQueryCommand.java | 105 - .../main/java/org/apache/qpid/qmf/QMFCommand.java | 54 - .../qpid/qmf/QMFCommandCompletionCommand.java | 63 - .../org/apache/qpid/qmf/QMFCommandDecoder.java | 98 - .../java/org/apache/qpid/qmf/QMFCommandHeader.java | 63 - .../java/org/apache/qpid/qmf/QMFEventClass.java | 42 - .../java/org/apache/qpid/qmf/QMFEventCommand.java | 47 - .../java/org/apache/qpid/qmf/QMFEventSeverity.java | 33 - .../org/apache/qpid/qmf/QMFGetQueryCommand.java | 205 -- .../main/java/org/apache/qpid/qmf/QMFMessage.java | 256 --- .../main/java/org/apache/qpid/qmf/QMFMethod.java | 157 -- .../org/apache/qpid/qmf/QMFMethodInvocation.java | 26 - .../apache/qpid/qmf/QMFMethodRequestCommand.java | 95 - .../apache/qpid/qmf/QMFMethodResponseCommand.java | 76 - .../main/java/org/apache/qpid/qmf/QMFObject.java | 81 - .../java/org/apache/qpid/qmf/QMFObjectClass.java | 44 - .../java/org/apache/qpid/qmf/QMFOperation.java | 67 - .../main/java/org/apache/qpid/qmf/QMFPackage.java | 67 - .../qpid/qmf/QMFPackageIndicationCommand.java | 44 - .../apache/qpid/qmf/QMFPackageQueryCommand.java | 98 - .../main/java/org/apache/qpid/qmf/QMFProperty.java | 120 -- .../apache/qpid/qmf/QMFSchemaRequestCommand.java | 102 - .../apache/qpid/qmf/QMFSchemaResponseCommand.java | 81 - .../main/java/org/apache/qpid/qmf/QMFService.java | 2086 -------------------- .../java/org/apache/qpid/qmf/QMFStatistic.java | 61 - .../src/main/java/org/apache/qpid/qmf/QMFType.java | 53 - .../java/org/apache/qpid/server/AMQChannel.java | 193 +- .../main/java/org/apache/qpid/server/Broker.java | 376 +--- .../java/org/apache/qpid/server/BrokerOptions.java | 156 +- .../src/main/java/org/apache/qpid/server/Main.java | 255 +-- .../org/apache/qpid/server/ProtocolExclusion.java | 74 - .../org/apache/qpid/server/ProtocolInclusion.java | 74 - .../qpid/server/TransactionTimeoutHelper.java | 69 +- .../org/apache/qpid/server/binding/Binding.java | 13 +- .../apache/qpid/server/binding/BindingFactory.java | 25 +- .../qpid/server/configuration/BindingConfig.java | 41 - .../server/configuration/BindingConfigType.java | 114 -- .../qpid/server/configuration/BridgeConfig.java | 48 - .../server/configuration/BridgeConfigType.java | 170 -- .../qpid/server/configuration/BrokerConfig.java | 71 - .../server/configuration/BrokerConfigType.java | 145 -- .../BrokerConfigurationStoreCreator.java | 102 + .../server/configuration/BrokerProperties.java | 54 + .../server/configuration/ConfigObjectType.java | 30 - .../qpid/server/configuration/ConfigProperty.java | 66 - .../qpid/server/configuration/ConfigStore.java | 201 -- .../server/configuration/ConfigurationEntry.java | 203 ++ .../configuration/ConfigurationEntryStore.java | 98 + .../server/configuration/ConfigurationManager.java | 54 - .../configuration/ConfigurationStoreFactory.java | 35 + .../server/configuration/ConfiguredObject.java | 37 - .../configuration/ConfiguredObjectRecoverer.java | 28 + .../server/configuration/ConnectionConfig.java | 49 - .../server/configuration/ConnectionConfigType.java | 146 -- .../qpid/server/configuration/ExchangeConfig.java | 60 - .../server/configuration/ExchangeConfigType.java | 115 -- .../configuration/ExchangeConfigurationPlugin.java | 29 - .../IllegalConfigurationException.java | 37 + .../qpid/server/configuration/LinkConfig.java | 56 - .../qpid/server/configuration/LinkConfigType.java | 137 -- .../qpid/server/configuration/QueueConfig.java | 86 - .../qpid/server/configuration/QueueConfigType.java | 123 -- .../server/configuration/QueueConfiguration.java | 45 +- .../server/configuration/RecovererProvider.java | 28 + .../server/configuration/ServerConfiguration.java | 1031 ---------- .../ServerNetworkTransportConfiguration.java | 90 - .../qpid/server/configuration/SessionConfig.java | 55 - .../server/configuration/SessionConfigType.java | 137 -- .../server/configuration/SubscriptionConfig.java | 47 - .../configuration/SubscriptionConfigType.java | 140 -- .../qpid/server/configuration/SystemConfig.java | 42 - .../server/configuration/SystemConfigImpl.java | 137 -- .../server/configuration/SystemConfigType.java | 132 -- .../qpid/server/configuration/TopicConfig.java | 78 - .../server/configuration/TopicConfiguration.java | 270 --- .../server/configuration/VirtualHostConfig.java | 32 - .../configuration/VirtualHostConfigType.java | 99 - .../configuration/VirtualHostConfiguration.java | 197 +- .../configuration/XmlConfigurationUtilities.java | 111 ++ .../plugins/AbstractConfiguration.java | 329 +++ .../configuration/plugins/ConfigurationPlugin.java | 488 ----- .../plugins/ConfigurationPluginFactory.java | 38 - .../SlowConsumerDetectionConfiguration.java | 86 - .../SlowConsumerDetectionPolicyConfiguration.java | 74 - .../SlowConsumerDetectionQueueConfiguration.java | 163 -- .../startup/AuthenticationProviderRecoverer.java | 55 + .../configuration/startup/BrokerRecoverer.java | 139 ++ .../startup/DefaultRecovererProvider.java | 112 ++ .../startup/GroupProviderRecoverer.java | 74 + .../configuration/startup/KeyStoreRecoverer.java | 40 + .../configuration/startup/PluginRecoverer.java | 66 + .../configuration/startup/PortRecoverer.java | 52 + .../configuration/startup/RecovererHelper.java | 44 + .../configuration/startup/TrustStoreRecoverer.java | 40 + .../startup/VirtualHostRecoverer.java | 51 + .../store/JsonConfigurationEntryStore.java | 711 +++++++ .../store/ManagementModeStoreHandler.java | 327 +++ .../store/StoreConfigurationChangeListener.java | 205 ++ .../factory/JsonConfigurationStoreFactory.java | 41 + .../configuration/updater/ChangeStateTask.java | 67 + .../configuration/updater/CreateChildTask.java | 78 + .../configuration/updater/SetAttributeTask.java | 74 + .../server/configuration/updater/TaskExecutor.java | 324 +++ .../qpid/server/exchange/AbstractExchange.java | 32 +- .../server/exchange/DefaultExchangeFactory.java | 101 +- .../server/exchange/DefaultExchangeRegistry.java | 1 + .../qpid/server/exchange/DirectExchange.java | 42 +- .../qpid/server/exchange/DirectExchangeType.java | 53 + .../org/apache/qpid/server/exchange/Exchange.java | 18 +- .../qpid/server/exchange/ExchangeFactory.java | 4 +- .../qpid/server/exchange/ExchangeInitialiser.java | 1 + .../apache/qpid/server/exchange/ExchangeType.java | 37 - .../qpid/server/exchange/FanoutExchange.java | 36 +- .../qpid/server/exchange/FanoutExchangeType.java | 51 + .../qpid/server/exchange/HeadersExchange.java | 36 +- .../qpid/server/exchange/HeadersExchangeType.java | 52 + .../apache/qpid/server/exchange/TopicExchange.java | 41 +- .../qpid/server/exchange/TopicExchangeType.java | 53 + .../org/apache/qpid/server/federation/Bridge.java | 913 --------- .../apache/qpid/server/federation/BrokerLink.java | 692 ------- .../handler/ConnectionSecureOkMethodHandler.java | 19 +- .../handler/ConnectionStartOkMethodHandler.java | 29 +- .../server/handler/ExchangeDeclareHandler.java | 2 +- .../qpid/server/handler/QueueDeclareHandler.java | 13 +- .../server/logging/AbstractRootMessageLogger.java | 5 +- .../qpid/server/logging/Log4jMessageLogger.java | 14 +- .../apache/qpid/server/logging/LogRecorder.java | 7 +- .../logging/actors/AbstractManagementActor.java | 68 + .../qpid/server/logging/actors/CurrentActor.java | 5 + .../server/logging/actors/HttpManagementActor.java | 62 + .../server/logging/actors/ManagementActor.java | 62 +- .../qpid/server/logging/log4j/LoggingFacade.java | 579 ------ .../logging/log4j/LoggingManagementFacade.java | 579 ++++++ .../ManagementConsole_logmessages.properties | 11 +- .../server/logging/subjects/ChannelLogSubject.java | 2 +- .../server/logging/subjects/LogSubjectFormat.java | 8 + .../qpid/server/message/MessageMetaData_1_0.java | 11 +- .../qpid/server/model/AuthenticationProvider.java | 14 + .../java/org/apache/qpid/server/model/Broker.java | 124 +- .../server/model/ConfigurationChangeListener.java | 1 + .../apache/qpid/server/model/ConfiguredObject.java | 22 +- .../java/org/apache/qpid/server/model/Group.java | 52 + .../org/apache/qpid/server/model/GroupMember.java | 52 + .../apache/qpid/server/model/GroupProvider.java | 55 + .../org/apache/qpid/server/model/KeyStore.java | 51 + .../java/org/apache/qpid/server/model/Model.java | 8 + .../java/org/apache/qpid/server/model/Plugin.java | 52 + .../java/org/apache/qpid/server/model/Port.java | 22 +- .../org/apache/qpid/server/model/Protocol.java | 97 +- .../org/apache/qpid/server/model/Transport.java | 26 +- .../org/apache/qpid/server/model/TrustStore.java | 65 + .../apache/qpid/server/model/UUIDGenerator.java | 15 + .../java/org/apache/qpid/server/model/User.java | 2 - .../org/apache/qpid/server/model/VirtualHost.java | 22 +- .../qpid/server/model/adapter/AbstractAdapter.java | 271 +-- .../model/adapter/AbstractKeyStoreAdapter.java | 198 ++ .../model/adapter/AbstractPluginAdapter.java | 152 ++ .../qpid/server/model/adapter/AmqpPortAdapter.java | 251 +++ .../adapter/AuthenticationProviderAdapter.java | 199 +- .../adapter/AuthenticationProviderFactory.java | 77 + .../qpid/server/model/adapter/BindingAdapter.java | 15 +- .../qpid/server/model/adapter/BrokerAdapter.java | 807 ++++++-- .../server/model/adapter/ConnectionAdapter.java | 63 +- .../qpid/server/model/adapter/ConsumerAdapter.java | 16 +- .../qpid/server/model/adapter/ExchangeAdapter.java | 25 +- .../server/model/adapter/GroupProviderAdapter.java | 550 ++++++ .../qpid/server/model/adapter/HTTPPortAdapter.java | 273 --- .../qpid/server/model/adapter/KeyStoreAdapter.java | 48 + .../qpid/server/model/adapter/PortAdapter.java | 169 +- .../qpid/server/model/adapter/PortFactory.java | 222 +++ .../qpid/server/model/adapter/QueueAdapter.java | 56 +- .../qpid/server/model/adapter/SessionAdapter.java | 19 +- .../server/model/adapter/TrustStoreAdapter.java | 43 + .../server/model/adapter/VirtualHostAdapter.java | 332 +++- .../model/adapter/VirtualHostAliasAdapter.java | 9 +- .../server/output/ProtocolOutputConverterImpl.java | 117 +- .../qpid/server/plugin/AccessControlFactory.java | 28 + .../plugin/AuthenticationManagerFactory.java | 31 + .../apache/qpid/server/plugin/ExchangeType.java | 36 + .../qpid/server/plugin/GroupManagerFactory.java | 28 + .../apache/qpid/server/plugin/PluginFactory.java | 32 + .../qpid/server/plugin/QpidServiceLoader.java | 72 + .../org/apache/qpid/server/plugins/Activator.java | 51 - .../qpid/server/plugins/OsgiSystemPackageUtil.java | 91 - .../server/plugins/OsgiSystemPackages.properties | 135 -- .../org/apache/qpid/server/plugins/Plugin.java | 32 - .../apache/qpid/server/plugins/PluginFactory.java | 32 - .../apache/qpid/server/plugins/PluginManager.java | 403 ---- .../qpid/server/protocol/AMQProtocolEngine.java | 99 +- .../qpid/server/protocol/AMQSessionModel.java | 3 +- .../protocol/MultiVersionProtocolEngine.java | 92 +- .../MultiVersionProtocolEngineFactory.java | 12 +- .../qpid/server/protocol/ProtocolEngine_0_10.java | 149 +- .../qpid/server/protocol/ProtocolEngine_1_0_0.java | 63 +- .../server/protocol/ProtocolEngine_1_0_0_SASL.java | 68 +- .../qpid/server/protocol/v1_0/Connection_1_0.java | 9 +- .../server/protocol/v1_0/ExchangeDestination.java | 2 +- .../qpid/server/protocol/v1_0/Message_1_0.java | 104 +- .../qpid/server/protocol/v1_0/Session_1_0.java | 22 +- .../org/apache/qpid/server/queue/AMQQueue.java | 26 +- .../apache/qpid/server/queue/AMQQueueFactory.java | 39 +- .../qpid/server/queue/InboundMessageAdapter.java | 2 +- .../apache/qpid/server/queue/IncomingMessage.java | 32 +- .../apache/qpid/server/queue/QueueEntryImpl.java | 2 +- .../apache/qpid/server/queue/SimpleAMQQueue.java | 103 +- .../qpid/server/registry/ApplicationRegistry.java | 624 +----- .../qpid/server/registry/BrokerConfigAdapter.java | 195 -- .../ConfigurationFileApplicationRegistry.java | 42 - .../qpid/server/registry/IApplicationRegistry.java | 94 - .../qpid/server/security/AbstractPlugin.java | 57 - .../qpid/server/security/AbstractProxyPlugin.java | 122 -- .../apache/qpid/server/security/AccessControl.java | 45 + .../qpid/server/security/AuthorizationHolder.java | 12 +- .../qpid/server/security/SecurityManager.java | 235 +-- .../qpid/server/security/SecurityPlugin.java | 47 - .../server/security/SecurityPluginActivator.java | 75 - .../server/security/SecurityPluginFactory.java | 30 - .../qpid/server/security/SubjectCreator.java | 137 ++ .../server/security/access/ObjectProperties.java | 206 +- .../qpid/server/security/access/ObjectType.java | 7 +- .../security/access/plugins/BasicPlugin.java | 43 - .../security/access/plugins/LegacyAccess.java | 86 - .../security/auth/AuthenticatedPrincipal.java | 127 ++ .../server/security/auth/AuthenticationResult.java | 75 +- .../security/auth/SubjectAuthenticationResult.java | 76 + .../server/security/auth/UsernamePrincipal.java | 77 + .../AbstractPasswordFilePrincipalDatabase.java | 2 +- .../security/auth/database/PrincipalDatabase.java | 2 + .../auth/database/PropertiesPrincipalDatabase.java | 169 -- ...bstractPrincipalDatabaseAuthManagerFactory.java | 71 + .../manager/AnonymousAuthenticationManager.java | 92 +- .../AnonymousAuthenticationManagerFactory.java | 40 + .../auth/manager/AuthenticationManager.java | 15 +- .../AuthenticationManagerPluginFactory.java | 32 - .../manager/AuthenticationManagerRegistry.java | 203 -- ...D5PasswordFileAuthenticationManagerFactory.java | 42 + .../manager/ExternalAuthenticationManager.java | 92 +- .../ExternalAuthenticationManagerFactory.java | 40 + .../manager/IAuthenticationManagerRegistry.java | 59 - .../manager/KerberosAuthenticationManager.java | 88 +- .../KerberosAuthenticationManagerFactory.java | 39 + ...inPasswordFileAuthenticationManagerFactory.java | 42 + .../PrincipalDatabaseAuthenticationManager.java | 249 +-- .../manager/SimpleLDAPAuthenticationManager.java | 254 +-- .../SimpleLDAPAuthenticationManagerFactory.java | 69 + .../auth/rmi/RMIPasswordAuthenticator.java | 88 +- .../server/security/auth/sasl/GroupPrincipal.java | 99 - .../auth/sasl/UsernamePasswordInitialiser.java | 1 + .../security/auth/sasl/UsernamePrincipal.java | 99 - .../auth/sasl/anonymous/AnonymousSaslServer.java | 4 +- .../auth/sasl/crammd5/CRAMMD5HexInitialiser.java | 6 + .../server/security/group/FileGroupDatabase.java | 287 +++ .../server/security/group/FileGroupManager.java | 147 ++ .../security/group/FileGroupManagerFactory.java | 51 + .../qpid/server/security/group/GroupDatabase.java | 34 + .../qpid/server/security/group/GroupManager.java | 40 + .../qpid/server/security/group/GroupPrincipal.java | 100 + .../security/group/GroupPrincipalAccessor.java | 54 + .../qpid/server/signal/SignalHandlerTask.java | 89 - .../apache/qpid/server/state/AMQStateManager.java | 33 +- .../server/store/ConfigurationRecoveryHandler.java | 14 +- .../server/store/DurableConfigurationStore.java | 11 +- .../qpid/server/store/MemoryMessageStore.java | 3 +- .../server/store/MemoryMessageStoreFactory.java | 39 + .../qpid/server/store/MessageStoreCreator.java | 66 + .../qpid/server/store/MessageStoreFactory.java | 28 + .../apache/qpid/server/store/NullMessageStore.java | 22 - .../java/org/apache/qpid/server/store/State.java | 4 +- .../qpid/server/store/derby/DerbyMessageStore.java | 350 +--- .../store/derby/DerbyMessageStoreFactory.java | 41 + .../qpid/server/subscription/SubscriptionImpl.java | 40 +- .../server/subscription/Subscription_0_10.java | 37 +- .../apache/qpid/server/transport/QpidAcceptor.java | 81 - .../qpid/server/transport/ServerConnection.java | 55 +- .../server/transport/ServerConnectionDelegate.java | 76 +- .../qpid/server/transport/ServerSession.java | 153 +- .../server/transport/ServerSessionDelegate.java | 15 +- .../server/txn/AsyncAutoCommitTransaction.java | 9 +- .../qpid/server/txn/AutoCommitTransaction.java | 11 +- .../qpid/server/txn/DistributedTransaction.java | 20 +- .../apache/qpid/server/txn/LocalTransaction.java | 77 +- .../apache/qpid/server/txn/ServerTransaction.java | 11 +- .../apache/qpid/server/util/MapValueConverter.java | 361 ++++ .../qpid/server/virtualhost/VirtualHost.java | 22 +- .../VirtualHostConfigRecoveryHandler.java | 56 +- .../qpid/server/virtualhost/VirtualHostImpl.java | 173 +- .../server/virtualhost/VirtualHostRegistry.java | 213 +- .../plugins/ConfiguredQueueBindingListener.java | 105 - .../virtualhost/plugins/SlowConsumerDetection.java | 174 -- .../plugins/VirtualHostHouseKeepingPlugin.java | 61 - .../virtualhost/plugins/VirtualHostPlugin.java | 42 - .../plugins/VirtualHostPluginFactory.java | 28 - .../SlowConsumerDetection_logmessages.properties | 23 - .../TopicDeletePolicy_logmessages.properties | 22 - .../plugins/policies/TopicDeletePolicy.java | 141 -- .../policies/TopicDeletePolicyConfiguration.java | 82 - .../policies/SlowConsumerPolicyPlugin.java | 29 - .../policies/SlowConsumerPolicyPluginFactory.java | 27 - ....server.configuration.ConfigurationStoreFactory | 19 + ...qpid.server.plugin.AuthenticationManagerFactory | 24 + .../org.apache.qpid.server.plugin.ExchangeType | 22 + ...g.apache.qpid.server.plugin.GroupManagerFactory | 19 + ...rg.apache.qpid.server.store.MessageStoreFactory | 20 + java/broker/src/main/resources/initial-store.json | 58 + .../org/apache/qpid/server/AMQChannelTest.java | 103 +- .../org/apache/qpid/server/BrokerOptionsTest.java | 181 +- .../test/java/org/apache/qpid/server/MainTest.java | 170 +- .../qpid/server/TransactionTimeoutHelperTest.java | 203 +- .../apache/qpid/server/ack/AcknowledgeTest.java | 71 +- .../BrokerConfigurationStoreCreatorTest.java | 144 ++ .../server/configuration/BrokerPropertiesTest.java | 51 + .../server/configuration/MockConnectionConfig.java | 171 -- .../configuration/QueueConfigurationTest.java | 157 +- .../configuration/ServerConfigurationTest.java | 1766 ----------------- .../configuration/TopicConfigurationTest.java | 131 -- .../VirtualHostConfigurationTest.java | 155 +- .../plugins/AbstractConfigurationTest.java | 210 ++ .../plugins/ConfigurationPluginTest.java | 210 -- .../configuration/startup/BrokerRecovererTest.java | 405 ++++ .../startup/DefaultRecovererProviderTest.java | 62 + .../startup/GroupProviderRecovererTest.java | 97 + .../startup/KeyStoreRecovererTest.java | 111 ++ .../configuration/startup/PluginRecovererTest.java | 117 ++ .../startup/TrustStoreRecovererTest.java | 108 + .../startup/VirtualHostRecovererTest.java | 124 ++ .../store/ConfigurationEntryStoreTestCase.java | 392 ++++ .../store/JsonConfigurationEntryStoreTest.java | 216 ++ .../store/ManagementModeStoreHandlerTest.java | 341 ++++ .../StoreConfigurationChangeListenerTest.java | 83 + .../configuration/updater/TaskExecutorTest.java | 296 +++ .../exchange/AbstractHeadersExchangeTestBase.java | 54 +- .../exchange/DefaultExchangeFactoryTest.java | 226 +++ .../qpid/server/exchange/HeadersBindingTest.java | 28 +- .../qpid/server/exchange/HeadersExchangeTest.java | 16 +- .../qpid/server/exchange/TopicExchangeTest.java | 53 +- .../qpid/server/logging/UnitTestMessageLogger.java | 5 +- .../logging/actors/AMQPChannelActorTest.java | 150 +- .../logging/actors/AMQPConnectionActorTest.java | 26 +- .../actors/AbstractManagementActorTest.java | 86 + .../server/logging/actors/BaseActorTestCase.java | 66 +- .../actors/BaseConnectionActorTestCase.java | 35 +- .../server/logging/actors/CurrentActorTest.java | 7 +- .../logging/actors/HttpManagementActorTest.java | 94 + .../server/logging/actors/ManagementActorTest.java | 40 +- .../qpid/server/logging/actors/QueueActorTest.java | 12 +- .../logging/actors/SubscriptionActorTest.java | 13 +- .../server/logging/log4j/LoggingFacadeTest.java | 245 --- .../logging/log4j/LoggingManagementFacadeTest.java | 243 +++ .../logging/messages/AbstractTestMessages.java | 13 +- .../logging/messages/ExchangeMessagesTest.java | 23 +- .../messages/ManagementConsoleMessagesTest.java | 21 +- .../logging/subjects/AbstractTestLogSubject.java | 47 +- .../logging/subjects/BindingLogSubjectTest.java | 17 +- .../logging/subjects/ChannelLogSubjectTest.java | 1 + .../logging/subjects/ConnectionLogSubjectTest.java | 26 +- .../logging/subjects/ExchangeLogSubjectTest.java | 16 +- .../subjects/MessageStoreLogSubjectTest.java | 16 +- .../logging/subjects/QueueLogSubjectTest.java | 15 +- .../subjects/SubscriptionLogSubjectTest.java | 24 +- .../qpid/server/model/BrokerShutdownTest.java | 189 ++ .../qpid/server/model/UUIDGeneratorTest.java | 6 +- .../adapter/AuthenticationProviderFactoryTest.java | 85 + .../qpid/server/model/adapter/PortFactoryTest.java | 212 ++ .../configuration/ConfigurationEntryTest.java | 129 ++ .../server/plugins/OsgiSystemPackageUtilTest.java | 94 - .../org/apache/qpid/server/plugins/PluginTest.java | 55 - .../protocol/InternalTestProtocolSession.java | 28 +- .../qpid/server/protocol/MaxChannelsTest.java | 42 +- .../MultiVersionProtocolEngineFactoryTest.java | 50 +- .../qpid/server/queue/AMQPriorityQueueTest.java | 28 +- .../qpid/server/queue/AMQQueueFactoryTest.java | 68 +- .../java/org/apache/qpid/server/queue/AckTest.java | 28 +- .../server/queue/InboundMessageAdapterTest.java | 97 + .../org/apache/qpid/server/queue/MockAMQQueue.java | 34 +- .../qpid/server/queue/SimpleAMQQueueTest.java | 74 +- .../server/queue/SimpleAMQQueueThreadPoolTest.java | 27 +- .../registry/ApplicationRegistryShutdownTest.java | 104 - .../qpid/server/security/SubjectCreatorTest.java | 138 ++ .../security/auth/AuthenticatedPrincipalTest.java | 147 ++ .../auth/AuthenticatedPrincipalTestHelper.java | 54 + .../security/auth/AuthenticationResultTest.java | 112 ++ .../server/security/auth/TestPrincipalUtils.java | 49 + .../security/auth/UsernamePrincipalTest.java | 70 + ...Base64MD5PasswordFilePrincipalDatabaseTest.java | 2 +- .../PlainPasswordFilePrincipalDatabaseTest.java | 2 +- .../auth/database/PropertiesPrincipalDatabase.java | 158 ++ .../AnonymousAuthenticationManagerTest.java | 47 +- .../manager/AuthenticationManagerRegistryTest.java | 304 --- ...sswordFileAuthenticationManagerFactoryTest.java | 111 ++ .../manager/ExternalAuthenticationManagerTest.java | 58 +- ...sswordFileAuthenticationManagerFactoryTest.java | 111 ++ ...PrincipalDatabaseAuthenticationManagerTest.java | 364 ++-- ...SimpleLDAPAuthenticationManagerFactoryTest.java | 48 + .../auth/rmi/RMIPasswordAuthenticatorTest.java | 183 +- .../security/auth/sasl/GroupPrincipalTest.java | 86 - .../security/auth/sasl/TestPrincipalDatabase.java | 6 + .../security/auth/sasl/TestPrincipalUtils.java | 48 - .../security/auth/sasl/UsernamePrincipalTest.java | 123 -- .../security/group/FileGroupDatabaseTest.java | 456 +++++ .../group/FileGroupManagerFactoryTest.java | 77 + .../security/group/FileGroupManagerTest.java | 197 ++ .../security/group/GroupPrincipalAccessorTest.java | 80 + .../server/security/group/GroupPrincipalTest.java | 88 + .../qpid/server/signal/SignalHandlerTaskTest.java | 119 -- .../store/DurableConfigurationStoreTest.java | 10 +- .../qpid/server/store/MessageStoreCreatorTest.java | 39 + .../apache/qpid/server/store/MessageStoreTest.java | 51 +- .../qpid/server/store/ReferenceCountingTest.java | 13 +- .../qpid/server/subscription/MockSubscription.java | 17 +- .../subscription/QueueBrowserUsesNoAckTest.java | 79 +- .../subscription/SubscriptionFactoryImplTest.java | 56 +- .../qpid/server/transport/ServerSessionTest.java | 48 +- .../server/txn/AsyncAutoCommitTransactionTest.java | 2 +- .../qpid/server/txn/AutoCommitTransactionTest.java | 8 +- .../qpid/server/txn/LocalTransactionTest.java | 127 +- .../apache/qpid/server/txn/MockServerMessage.java | 6 - .../apache/qpid/server/util/BrokerTestHelper.java | 209 ++ .../qpid/server/util/InternalBrokerBaseCase.java | 372 ---- .../qpid/server/util/TestApplicationRegistry.java | 121 -- .../qpid/server/virtualhost/MockVirtualHost.java | 69 +- .../server/virtualhost/VirtualHostImplTest.java | 107 +- .../SlowConsumerDetectionConfigurationTest.java | 347 ---- ...owConsumerDetectionPolicyConfigurationTest.java | 105 - ...lowConsumerDetectionQueueConfigurationTest.java | 186 -- .../TopicDeletePolicyConfigurationTest.java | 89 - .../plugins/policies/TopicDeletePolicyTest.java | 294 --- .../qpid/server/logging/messages/LogMessages.vm | 19 +- java/build.deps | 22 +- java/build.xml | 6 +- java/client/build.xml | 2 +- .../main/java/org/apache/qpid/example/Drain.java | 2 +- .../java/org/apache/qpid/example/ListReceiver.java | 101 + .../java/org/apache/qpid/example/ListSender.java | 86 + .../main/java/org/apache/qpid/example/Spout.java | 1 + java/client/src/main/java/client.bnd | 2 +- .../org/apache/qpid/client/AMQBrokerDetails.java | 9 +- .../java/org/apache/qpid/client/AMQConnection.java | 50 +- .../apache/qpid/client/AMQConnectionDelegate.java | 2 + .../qpid/client/AMQConnectionDelegate_0_10.java | 36 +- .../qpid/client/AMQConnectionDelegate_8_0.java | 50 +- .../apache/qpid/client/AMQConnectionFactory.java | 2 +- .../org/apache/qpid/client/AMQDestination.java | 101 +- .../java/org/apache/qpid/client/AMQSession.java | 225 +-- .../org/apache/qpid/client/AMQSession_0_10.java | 408 ++-- .../org/apache/qpid/client/AMQSession_0_8.java | 177 +- .../main/java/org/apache/qpid/client/AMQTopic.java | 4 +- .../apache/qpid/client/BasicMessageConsumer.java | 19 +- .../qpid/client/BasicMessageConsumer_0_10.java | 23 +- .../qpid/client/BasicMessageConsumer_0_8.java | 22 +- .../apache/qpid/client/BasicMessageProducer.java | 100 +- .../qpid/client/BasicMessageProducer_0_10.java | 44 +- .../qpid/client/BasicMessageProducer_0_8.java | 30 +- .../org/apache/qpid/client/HeartbeatListener.java | 37 + .../java/org/apache/qpid/client/XASessionImpl.java | 2 +- .../handler/ConnectionCloseMethodHandler.java | 24 +- .../client/message/AMQMessageDelegate_0_10.java | 21 +- .../client/message/AMQPEncodedListMessage.java | 935 +++++++++ .../message/AMQPEncodedListMessageFactory.java | 44 + .../qpid/client/message/JMSObjectMessage.java | 9 +- .../qpid/client/message/JMSStreamMessage.java | 5 + .../client/message/MessageFactoryRegistry.java | 1 + .../client/messaging/address/AddressHelper.java | 203 +- .../apache/qpid/client/messaging/address/Link.java | 90 +- .../apache/qpid/client/messaging/address/Node.java | 85 +- .../qpid/client/protocol/AMQProtocolHandler.java | 152 +- .../qpid/client/protocol/AMQProtocolSession.java | 9 +- .../qpid/client/protocol/HeartbeatDiagnostics.java | 125 -- .../qpid/client/security/DynamicSaslRegistrar.java | 64 +- .../apache/qpid/client/security/JCAProvider.java | 10 +- .../apache/qpid/client/state/AMQStateManager.java | 7 +- .../client/transport/ClientConnectionDelegate.java | 18 + .../java/org/apache/qpid/jms/ConnectionURL.java | 17 +- .../main/java/org/apache/qpid/jms/ListMessage.java | 55 + .../java/org/apache/qpid/jms/MessageProducer.java | 14 - .../src/main/java/org/apache/qpid/jms/Session.java | 3 + .../apache/qpid/client/AMQConnectionUnitTest.java | 67 +- .../apache/qpid/client/AMQSession_0_10Test.java | 15 +- .../qpid/client/BasicMessageConsumer_0_8_Test.java | 6 +- .../message/AMQPEncodedListMessageUnitTest.java | 153 ++ .../messaging/address/AddressHelperTest.java | 146 ++ .../client/security/DynamicSaslRegistrarTest.java | 140 ++ .../client/BrokerDetails/BrokerDetailsTest.java | 42 + .../client/connectionurl/ConnectionURLTest.java | 128 +- .../client/destinationurl/DestinationURLTest.java | 120 ++ .../qpid/test/unit/message/TestAMQSession.java | 14 +- java/common.xml | 11 +- java/common/bin/qpid-run | 8 +- java/common/build.xml | 21 +- .../src/org/apache/qpid/gentools/AmqpClass.java | 197 ++ .../src/org/apache/qpid/gentools/AmqpClassMap.java | 29 + .../src/org/apache/qpid/gentools/AmqpConstant.java | 191 ++ .../org/apache/qpid/gentools/AmqpConstantSet.java | 152 ++ .../src/org/apache/qpid/gentools/AmqpDomain.java | 89 + .../org/apache/qpid/gentools/AmqpDomainMap.java | 128 ++ .../apache/qpid/gentools/AmqpDomainVersionMap.java | 62 + .../src/org/apache/qpid/gentools/AmqpField.java | 269 +++ .../src/org/apache/qpid/gentools/AmqpFieldMap.java | 452 +++++ .../src/org/apache/qpid/gentools/AmqpFlagMap.java | 77 + .../src/org/apache/qpid/gentools/AmqpMethod.java | 351 ++++ .../org/apache/qpid/gentools/AmqpMethodMap.java | 36 + .../src/org/apache/qpid/gentools/AmqpModel.java | 132 ++ .../apache/qpid/gentools/AmqpOrdinalFieldMap.java | 96 + .../qpid/gentools/AmqpOrdinalVersionMap.java | 76 + .../qpid/gentools/AmqpOverloadedParameterMap.java | 29 + .../apache/qpid/gentools/AmqpParseException.java | 30 + .../qpid/gentools/AmqpTemplateException.java | 30 + .../qpid/gentools/AmqpTypeMappingException.java | 30 + .../src/org/apache/qpid/gentools/AmqpVersion.java | 72 + .../org/apache/qpid/gentools/AmqpVersionSet.java | 79 + .../qpid/gentools/BitFieldGenerateMethod.java | 29 + .../qpid/gentools/CommandGenerateMethod.java | 26 + .../apache/qpid/gentools/ConsolidatedField.java | 120 ++ .../src/org/apache/qpid/gentools/CppGenerator.java | 1716 ++++++++++++++++ .../org/apache/qpid/gentools/DotnetGenerator.java | 382 ++++ .../org/apache/qpid/gentools/GenerateMethod.java | 27 + .../src/org/apache/qpid/gentools/Generator.java | 857 ++++++++ .../org/apache/qpid/gentools/JavaGenerator.java | 1826 +++++++++++++++++ .../apache/qpid/gentools/LanguageConverter.java | 42 + .../src/org/apache/qpid/gentools/Main.java | 301 +++ .../qpid/gentools/MangledGenerateMethod.java | 26 + .../src/org/apache/qpid/gentools/NodeAware.java | 47 + .../src/org/apache/qpid/gentools/Printable.java | 28 + .../apache/qpid/gentools/SingleVersionClass.java | 103 + .../apache/qpid/gentools/SingleVersionField.java | 68 + .../apache/qpid/gentools/SingleVersionMethod.java | 154 ++ .../apache/qpid/gentools/SingleVersionModel.java | 71 + .../qpid/gentools/TargetDirectoryException.java | 30 + .../src/org/apache/qpid/gentools/Utils.java | 159 ++ .../qpid/gentools/VersionConsistencyCheck.java | 26 + java/common/protocol-version.xml | 70 - java/common/src/main/java/common.bnd | 2 +- .../qpid/configuration/ClientProperties.java | 15 + .../org/apache/qpid/framing/AMQShortString.java | 19 +- .../java/org/apache/qpid/framing/FieldTable.java | 1 + .../qpid/properties/ConnectionStartProperties.java | 27 +- .../org/apache/qpid/protocol/ProtocolEngine.java | 5 +- .../java/org/apache/qpid/transport/Connection.java | 88 +- .../transport/NetworkTransportConfiguration.java | 8 - .../org/apache/qpid/transport/ServerDelegate.java | 5 +- .../java/org/apache/qpid/transport/Session.java | 22 +- .../network/IncomingNetworkTransport.java | 4 +- .../qpid/transport/network/NetworkConnection.java | 4 + .../network/OutgoingNetworkTransport.java | 5 +- .../org/apache/qpid/transport/network/Ticker.java | 29 + .../qpid/transport/network/TransportActivity.java | 33 + .../transport/network/io/IdleTimeoutTicker.java | 87 + .../transport/network/io/IoNetworkConnection.java | 31 +- .../transport/network/io/IoNetworkTransport.java | 51 +- .../qpid/transport/network/io/IoReceiver.java | 100 +- .../main/java/org/apache/qpid/url/BindingURL.java | 3 + .../main/java/org/apache/qpid/util/FileUtils.java | 13 + .../main/java/org/apache/qpid/util/NetMatcher.java | 300 --- .../org/apache/qpid/framing/FieldTableTest.java | 938 +++++++++ .../qpid/framing/PropertyFieldTableTest.java | 980 --------- .../org/apache/qpid/test/utils/QpidTestCase.java | 10 +- .../org/apache/qpid/test/utils/TestFileUtils.java | 90 + .../org/apache/qpid/transport/ConnectionTest.java | 7 + .../qpid/transport/TestNetworkConnection.java | 12 + .../qpid/transport/network/TransportTest.java | 5 +- .../network/io/IdleTimeoutTickerTest.java | 257 +++ java/ivy.nexus.xml | 42 + java/ivy.retrieve.xml | 3 +- java/ivysettings.retrieve.xml | 2 +- java/jca/README-JBOSS-EAP6.txt | 183 ++ java/jca/README-JBOSS.txt | 26 +- java/jca/build.xml | 25 +- .../rar/src/main/resources/META-INF/jboss-ra.xml | 33 + java/jca/rar/src/main/resources/META-INF/ra.xml | 230 +++ .../qpid/ra/admin/QpidConnectionFactoryProxy.java | 73 +- java/jca/src/main/resources/META-INF/jboss-ra.xml | 33 - java/jca/src/main/resources/META-INF/ra.xml | 230 --- .../common/src/main/java/management-common.bnd | 2 +- .../common/mbeans/ConfigurationManagement.java | 41 - .../apache/qpid/example/jmxexample/AddQueue.java | 41 +- java/module.xml | 208 +- java/perftests/build.xml | 2 +- .../1001-MessageSize-Transient-ByteSec.chartdef | 37 + .../chartdefs/1001-MessageSize-Transient.chartdef | 32 - .../1002-MessageSize-Persistent-ByteSec.chartdef | 37 + .../chartdefs/1002-MessageSize-Persistent.chartdef | 32 - .../1003-MessageSize-Transient-MsgSec.chartdef | 37 + .../1004-MessageSize-Persistent-MsgSec.chartdef | 37 + .../1011-VaryingNumberOfProducers-AutoAck.chartdef | 47 + .../1011-VaryingNumberOfProducers.chartdef | 40 - .../1012-VaryingNumberOfConsumers-AutoAck.chartdef | 47 + .../1012-VaryingNumberOfConsumers.chartdef | 40 - ...-VaryingNumberOfProducers-SessionTrans.chartdef | 47 + ...-VaryingNumberOfConsumers-SessionTrans.chartdef | 47 + .../1021-AcknowledgementModes-Persistent.chartdef | 13 +- .../1022-AcknowledgementModes-Transient.chartdef | 10 +- .../etc/chartdefs/1030-BatchSize-Equal.chartdef | 37 + .../etc/chartdefs/1030-BatchSize.chartdef | 33 - .../etc/chartdefs/1031-BatchSize-Unequal.chartdef | 53 + .../etc/chartdefs/1040-QueueTypes.chartdef | 10 +- ...mberOfProducerSessionsSingleConnection.chartdef | 49 + ...sWithNonOverlappingSelectors-Transient.chartdef | 37 + ...WithNonOverlappingSelectors-Persistent.chartdef | 43 + ...mersWithOverlappingSelectors-Transient.chartdef | 36 + ...ersWithOverlappingSelectors-Persistent.chartdef | 42 + .../1500-Topic-NumberOfConsumers.chartdef | 11 +- .../chartdefs/1501-Topic-NumberOfTopics.chartdef | 11 +- .../etc/chartdefs/1502-Topic-Persistence.chartdef | 13 +- .../etc/chartdefs/1503-Topic-AckModes.chartdef | 13 +- .../2001-Latency-MessageSize-Transient.chartdef | 6 + .../2002-Latency-MessageSize-Persistent.chartdef | 6 + ...sWithNonOverlappingSelectors-Transient.chartdef | 6 + ...euesWithOverlappingSelectors-Transient.chartdef | 6 + ...WithNonOverlappingSelectors-Persistent.chartdef | 6 + ...uesWithOverlappingSelectors-Persistent.chartdef | 6 + ...31-Latency-VaryingNumberOfParticipants.chartdef | 7 + .../etc/chartdefs/2041-Latency-QueueTypes.chartdef | 6 + .../1001-Large-Messages-Transient.chartdef | 29 + .../1002-Large-Messages-Persistent.chartdef | 29 + ...ltipleProducersAndConsumers-Persistent.chartdef | 30 + .../timeseries/1030-Batch-Size-Small.chartdef | 30 + .../timeseries/1031-Batch-Size-Large.chartdef | 30 + .../chartdefs/timeseries/1040-SortedQueue.chartdef | 30 + java/perftests/etc/perftests-jndi.properties | 4 + java/perftests/etc/run-perftests.sh | 37 + java/perftests/etc/testdefs/BatchSize.js | 102 + java/perftests/etc/testdefs/BatchSize.json | 84 - .../etc/testdefs/BatchSizeConsumerVaries.js | 102 + .../etc/testdefs/BatchSizeProducerVaries.js | 102 + .../QueueConsumersWithNonOverlappingSelectors.js | 120 ++ .../QueueConsumersWithOverlappingSelectors.js | 131 ++ java/perftests/etc/testdefs/Topic-AckModes.js | 9 +- .../etc/testdefs/Topic-NumberOfConsumers.js | 4 + .../perftests/etc/testdefs/Topic-NumberOfTopics.js | 4 + java/perftests/etc/testdefs/Topic-Persistence.js | 8 +- .../etc/testdefs/VaryingNumberOfParticipants.json | 272 ++- ...yingNumberOfProducerSessionsSingleConnection.js | 95 + java/perftests/etc/visualisation-timeseries.sh | 33 + java/perftests/etc/visualisation.sh | 35 + java/perftests/example/brokerconfig/log4j.xml | 2 +- java/perftests/example/perftests-jndi.properties | 3 + java/perftests/example/run.sh | 2 +- .../org/apache/qpid/disttest/ArgumentParser.java | 6 +- .../org/apache/qpid/disttest/ConfigFileHelper.java | 11 - .../org/apache/qpid/disttest/ControllerRunner.java | 84 +- .../apache/qpid/disttest/ResultsFileWriter.java | 112 ++ .../qpid/disttest/client/ConsumerParticipant.java | 17 +- .../qpid/disttest/client/ParticipantExecutor.java | 10 +- .../qpid/disttest/client/ProducerParticipant.java | 56 +- .../qpid/disttest/controller/ClientRegistry.java | 36 +- .../disttest/controller/ResultsForAllTests.java | 21 + .../disttest/controller/config/ConsumerConfig.java | 6 +- .../controller/config/ParticipantConfig.java | 4 + .../disttest/controller/config/ProducerConfig.java | 2 +- .../apache/qpid/disttest/db/ResultsDbWriter.java | 467 +++++ .../qpid/disttest/jms/ClientJmsDelegate.java | 64 +- .../qpid/disttest/jms/ControllerJmsDelegate.java | 4 +- .../apache/qpid/disttest/jms/NoOpQueueCreator.java | 5 +- .../apache/qpid/disttest/jms/QpidQueueCreator.java | 101 +- .../org/apache/qpid/disttest/jms/QueueCreator.java | 5 +- .../message/ConsumerParticipantResult.java | 4 + .../disttest/message/CreateConsumerCommand.java | 11 - .../disttest/message/CreateParticpantCommand.java | 11 + .../disttest/message/ParticipantAttribute.java | 42 +- .../qpid/disttest/message/ParticipantResult.java | 54 +- .../message/ProducerParticipantResult.java | 4 +- .../disttest/results/aggregation/ITestResult.java | 2 - .../aggregation/ParticipantResultAggregator.java | 11 + .../results/aggregation/TestResultAggregator.java | 24 + .../disttest/results/formatting/CSVFormater.java | 89 - .../disttest/results/formatting/CSVFormatter.java | 91 + .../apache/qpid/disttest/ConfigFileHelperTest.java | 8 - .../qpid/disttest/ResultsFileWriterTest.java | 85 + .../java/org/apache/qpid/disttest/VisitorTest.java | 5 +- .../disttest/client/ClientCommandVisitorTest.java | 4 +- .../apache/qpid/disttest/client/ClientTest.java | 5 +- .../disttest/client/ConsumerParticipantTest.java | 15 +- .../qpid/disttest/client/MessageProviderTest.java | 5 +- .../disttest/client/ParticipantExecutorTest.java | 25 +- .../disttest/client/ParticipantRegistryTest.java | 5 +- .../client/ParticipantResultFactoryTest.java | 5 +- .../disttest/client/ProducerParticipantTest.java | 34 +- .../client/property/ListPropertyValueTest.java | 8 +- .../client/property/PropertyValueFactoryTest.java | 4 +- .../client/property/RandomPropertyValueTest.java | 6 +- .../client/property/RangePropertyValueTest.java | 6 +- .../client/property/SimplePropertyValueTest.java | 4 +- .../client/utils/ExecutorWithNoLimitsTest.java | 4 +- .../client/utils/ExecutorWithTimeLimitTest.java | 6 +- .../disttest/controller/ClientRegistryTest.java | 44 +- .../qpid/disttest/controller/ControllerTest.java | 10 +- .../controller/ParticipatingClientsTest.java | 4 +- .../qpid/disttest/controller/TestRunnerTest.java | 5 +- .../controller/config/ClientConfigTest.java | 5 +- .../config/ConfigReaderTest-test-config.js | 22 +- .../controller/config/ConfigReaderTest.java | 9 +- .../disttest/controller/config/ConfigTest.java | 4 +- .../controller/config/ConnectionConfigTest.java | 5 +- .../controller/config/ConsumerConfigTest.java | 5 +- .../JavaScriptConfigEvaluatorTest-test-config.js | 22 +- .../config/JavaScriptConfigEvaluatorTest.java | 7 +- .../config/MessageProviderConfigTest.java | 5 +- .../controller/config/ParticipantConfigTest.java | 2 +- .../controller/config/ProducerConfigTest.java | 5 +- .../controller/config/SessionConfigTest.java | 5 +- .../disttest/controller/config/TestConfigTest.java | 5 +- .../controller/config/TestInstanceTest.java | 5 +- .../qpid/disttest/db/ResultsDbWriterTest.java | 158 ++ .../qpid/disttest/jms/JmsMessageAdaptorTest.java | 5 +- .../qpid/disttest/message/JsonHandlerTest.java | 5 +- .../disttest/message/ParticipantResultTest.java | 11 +- .../qpid/disttest/results/ResultsTestFixture.java | 138 ++ .../results/aggregation/AggregatorTest.java | 5 +- .../ParticipantResultAggregatorTest.java | 30 +- .../results/aggregation/SeriesStatisticsTest.java | 4 +- .../aggregation/TestResultAggregatorTest.java | 45 +- .../results/formatting/CSVFormaterTest.java | 146 -- .../results/formatting/CSVFormatterTest.java | 62 + .../CSVOrderParticipantResultComparatorTest.java | 6 +- .../disttest/results/formatting/expectedOutput.csv | 4 +- .../systest/disttest/QpidQueueCreatorTest.java | 42 +- .../qpid/systest/disttest/SystemTestConstants.java | 6 +- .../systest/disttest/endtoend/EndToEndTest.java | 13 +- .../systest/disttest/perftests.systests.properties | 3 + java/perftests/visualisation-jfc/build.xml | 4 +- .../apache/qpid/disttest/charting/ChartType.java | 2 +- .../qpid/disttest/charting/ChartingUtil.java | 67 +- .../charting/chartbuilder/BarChart3DBuilder.java | 2 +- .../charting/chartbuilder/BarChartBuilder.java | 2 +- .../charting/chartbuilder/BaseChartBuilder.java | 72 +- .../CategoryDataSetBasedChartBuilder.java | 60 +- .../CategoryStrokeAndPaintApplier.java | 41 + .../charting/chartbuilder/ChartBuilderFactory.java | 4 +- .../charting/chartbuilder/ColorFactory.java | 66 + .../charting/chartbuilder/LineChart3DBuilder.java | 2 +- .../charting/chartbuilder/LineChartBuilder.java | 2 +- .../charting/chartbuilder/SeriesPainter.java | 63 + .../chartbuilder/SeriesStrokeAndPaintApplier.java | 35 + .../chartbuilder/StatisticalBarCharBuilder.java | 111 -- .../chartbuilder/StatisticalBarChartBuilder.java | 114 ++ .../charting/chartbuilder/TimeSeriesHolder.java | 70 + .../chartbuilder/TimeSeriesLineChartBuilder.java | 59 + .../chartbuilder/XYDataSetBasedChartBuilder.java | 70 +- .../charting/definition/ChartingDefinition.java | 12 +- .../definition/ChartingDefinitionCreator.java | 6 +- .../charting/definition/SeriesDefinition.java | 27 +- .../definition/SeriesDefinitionCreator.java | 7 +- .../charting/seriesbuilder/DatasetHolder.java | 37 + .../seriesbuilder/JdbcCsvSeriesBuilder.java | 141 -- .../charting/seriesbuilder/JdbcSeriesBuilder.java | 157 ++ .../charting/seriesbuilder/JdbcUrlGenerator.java | 81 + .../charting/seriesbuilder/SeriesBuilder.java | 15 +- .../seriesbuilder/SeriesBuilderCallback.java | 30 - .../disttest/charting/seriesbuilder/SeriesRow.java | 98 + .../qpid/disttest/charting/writer/ChartWriter.java | 44 +- .../chartbuilder/BaseChartBuilderTest.java | 125 ++ .../chartbuilder/ChartBuilderFactoryTest.java | 13 +- .../charting/chartbuilder/ChartProductionTest.java | 130 +- .../charting/chartbuilder/ColorFactoryTest.java | 42 + .../TimeSeriesBuilderCallbackTest.java | 72 + .../definition/ChartingDefinitionCreatorTest.java | 13 +- .../definition/SeriesDefinitionCreatorTest.java | 32 +- .../seriesbuilder/JdbcCsvSeriesBuilderTest.java | 94 - .../seriesbuilder/JdbcSeriesBuilderTest.java | 103 + .../seriesbuilder/JdbcUrlGeneratorTest.java | 85 + .../charting/seriesbuilder/SeriesRowTest.java | 64 + .../disttest/charting/writer/ChartWriterTest.java | 35 +- .../charting/writer/expected-chart-summary.html | 14 +- java/systests/build.xml | 4 +- java/systests/etc/config-systests-bdb-settings.xml | 26 - java/systests/etc/config-systests-bdb.xml | 29 - .../etc/config-systests-derby-mem-settings.xml | 26 - java/systests/etc/config-systests-derby-mem.xml | 29 - .../etc/config-systests-derby-settings.xml | 26 - java/systests/etc/config-systests-derby.xml | 29 - java/systests/etc/config-systests-firewall-2.xml | 83 - java/systests/etc/config-systests-firewall-3.xml | 85 - .../etc/config-systests-firewall-settings.xml | 30 - java/systests/etc/config-systests-firewall.xml | 30 - java/systests/etc/config-systests-settings.xml | 103 - java/systests/etc/config-systests.json | 64 + java/systests/etc/groups-systests | 29 + .../etc/virtualhosts-systests-bdb-settings.xml | 26 +- .../virtualhosts-systests-derby-mem-settings.xml | 25 +- .../etc/virtualhosts-systests-derby-settings.xml | 25 +- .../etc/virtualhosts-systests-settings.xml | 125 -- .../qpid/client/AMQQueueDeferredOrderingTest.java | 12 +- .../java/org/apache/qpid/client/HeartbeatTest.java | 116 ++ .../client/failover/FailoverBehaviourTest.java | 51 +- .../failover/MultipleBrokersFailoverTest.java | 285 +++ .../java/org/apache/qpid/client/ssl/SSLTest.java | 291 ++- .../ra/admin/QpidConnectionFactoryProxyTest.java | 120 ++ .../org/apache/qpid/server/BrokerStartupTest.java | 8 +- .../qpid/server/SupportedProtocolVersionsTest.java | 124 +- .../configuration/ServerConfigurationFileTest.java | 75 - .../apache/qpid/server/failure/HeapExhaustion.java | 237 --- .../qpid/server/logging/AbstractTestLogging.java | 39 +- .../server/logging/AccessControlLoggingTest.java | 42 +- .../apache/qpid/server/logging/AlertingTest.java | 52 +- .../qpid/server/logging/BrokerLoggingTest.java | 98 +- .../server/logging/SubscriptionLoggingTest.java | 8 +- .../server/logging/VirtualHostLoggingTest.java | 15 +- .../persistent/NoLocalAfterRecoveryTest.java | 2 +- .../queue/MultipleTransactedBatchProducerTest.java | 5 +- .../server/security/acl/AbstractACLTestCase.java | 23 +- .../server/security/acl/ExternalACLJMXTest.java | 34 +- .../qpid/server/security/acl/ExternalACLTest.java | 44 +- .../auth/manager/ExternalAuthenticationTest.java | 184 ++ .../MultipleAuthenticationManagersTest.java | 38 +- .../security/firewall/FirewallConfigTest.java | 283 --- .../qpid/server/stats/StatisticsReportingTest.java | 89 +- .../apache/qpid/server/store/SlowMessageStore.java | 31 - .../qpid/server/store/StoreOverfullTest.java | 6 +- .../org/apache/qpid/systest/GlobalQueuesTest.java | 223 --- .../org/apache/qpid/systest/GlobalTopicsTest.java | 31 - .../qpid/systest/MergeConfigurationTest.java | 109 - .../org/apache/qpid/systest/SubscriptionTest.java | 146 -- .../org/apache/qpid/systest/TestingBaseCase.java | 240 --- .../java/org/apache/qpid/systest/TopicTest.java | 85 - .../management/jmx/BrokerManagementTest.java | 126 ++ .../management/jmx/ConnectionManagementTest.java | 283 +++ .../management/jmx/LoggingManagementTest.java | 147 ++ .../management/jmx/ManagementActorLoggingTest.java | 480 +++++ .../management/jmx/ManagementLoggingTest.java | 330 ++++ .../management/jmx/QueueManagementTest.java | 778 ++++++++ .../systest/management/jmx/StatisticsTest.java | 210 ++ .../systest/management/jmx/UserManagementTest.java | 260 +++ .../UserManagementWithBase64MD5PasswordsTest.java | 37 + .../java/org/apache/qpid/systest/rest/Asserts.java | 270 +++ .../rest/AuthenticationProviderRestTest.java | 73 + .../qpid/systest/rest/BasicAuthRestTest.java | 121 ++ .../apache/qpid/systest/rest/BindingRestTest.java | 130 ++ .../qpid/systest/rest/BrokerRestHttpsTest.java | 69 + .../apache/qpid/systest/rest/BrokerRestTest.java | 120 ++ .../qpid/systest/rest/ConnectionRestTest.java | 213 ++ .../apache/qpid/systest/rest/ExchangeRestTest.java | 87 + .../qpid/systest/rest/GroupProviderRestTest.java | 160 ++ .../apache/qpid/systest/rest/GroupRestTest.java | 109 + .../qpid/systest/rest/LogRecordsRestTest.java | 42 + .../apache/qpid/systest/rest/MessagesRestTest.java | 354 ++++ .../org/apache/qpid/systest/rest/PortRestTest.java | 64 + .../apache/qpid/systest/rest/QpidRestTestCase.java | 84 + .../apache/qpid/systest/rest/QueueRestTest.java | 225 +++ .../apache/qpid/systest/rest/RestTestHelper.java | 452 +++++ .../org/apache/qpid/systest/rest/SaslRestTest.java | 435 ++++ .../qpid/systest/rest/StructureRestTest.java | 114 ++ .../org/apache/qpid/systest/rest/UserRestTest.java | 99 + .../qpid/systest/rest/VirtualHostRestTest.java | 576 ++++++ .../qpid/systest/rest/acl/GroupRestACLTest.java | 197 ++ .../qpid/systest/rest/acl/UserRestACLTest.java | 200 ++ .../apache/qpid/test/client/RollbackOrderTest.java | 20 +- .../destination/AddressBasedDestinationTest.java | 200 +- .../qpid/test/client/failover/FailoverTest.java | 25 +- .../test/client/message/JMSDestinationTest.java | 3 +- .../test/client/timeouts/SyncWaitDelayTest.java | 6 +- .../test/unit/basic/InvalidDestinationTest.java | 101 +- .../client/DynamicQueueExchangeCreateTest.java | 168 +- .../test/unit/client/MaxDeliveryCountTest.java | 13 +- .../client/channelclose/ChannelCloseOkTest.java | 236 --- .../unit/client/channelclose/ChannelCloseTest.java | 399 ---- .../close/JavaServerCloseRaceConditionTest.java | 4 +- .../test/unit/topic/DurableSubscriptionTest.java | 2 +- .../transacted/TransactionTimeoutDisabledTest.java | 2 +- .../unit/transacted/TransactionTimeoutTest.java | 28 +- .../transacted/TransactionTimeoutTestCase.java | 19 +- .../qpid/test/utils/BrokerCommandHelper.java | 79 + .../qpid/test/utils/BrokerCommandHelperTest.java | 61 + .../qpid/test/utils/InternalBrokerHolder.java | 26 +- .../org/apache/qpid/test/utils/JMXTestUtils.java | 62 +- .../apache/qpid/test/utils/QpidBrokerTestCase.java | 502 +++-- .../test/utils/QpidClientConnectionHelper.java | 295 --- .../qpid/test/utils/TestBrokerConfiguration.java | 219 ++ .../apache/qpid/test/utils/TestSSLConstants.java | 30 + .../java/org/apache/qpid/test/utils/TestUtils.java | 54 + .../main/java/org/apache/qpid/util/LogMonitor.java | 39 + java/test-profiles/CPPExcludes | 24 +- java/test-profiles/Excludes | 1 - java/test-profiles/Java010Excludes | 6 +- java/test-profiles/JavaTransientExcludes | 2 + java/test-profiles/cpp.ssl.excludes | 2 - java/test-profiles/java-bdb-spawn.0-10.testprofile | 6 +- java/test-profiles/java-bdb-spawn.0-8.testprofile | 6 +- .../test-profiles/java-bdb-spawn.0-9-1.testprofile | 6 +- java/test-profiles/java-bdb-spawn.0-9.testprofile | 6 +- java/test-profiles/java-bdb.0-10.testprofile | 6 +- java/test-profiles/java-bdb.0-8.testprofile | 6 +- java/test-profiles/java-bdb.0-9-1.testprofile | 6 +- java/test-profiles/java-bdb.0-9.testprofile | 6 +- java/test-profiles/java-dby-mem.0-10.testprofile | 8 +- java/test-profiles/java-dby-mem.0-8.testprofile | 8 +- java/test-profiles/java-dby-mem.0-9-1.testprofile | 8 +- java/test-profiles/java-dby-mem.0-9.testprofile | 8 +- java/test-profiles/java-dby-spawn.0-10.testprofile | 6 +- java/test-profiles/java-dby-spawn.0-8.testprofile | 6 +- .../test-profiles/java-dby-spawn.0-9-1.testprofile | 6 +- java/test-profiles/java-dby-spawn.0-9.testprofile | 6 +- java/test-profiles/java-dby.0-10.testprofile | 6 +- java/test-profiles/java-dby.0-8.testprofile | 6 +- java/test-profiles/java-dby.0-9-1.testprofile | 6 +- java/test-profiles/java-dby.0-9.testprofile | 6 +- java/test-profiles/java-mms-spawn.0-10.testprofile | 5 +- java/test-profiles/java-mms-spawn.0-8.testprofile | 5 +- .../test-profiles/java-mms-spawn.0-9-1.testprofile | 5 +- java/test-profiles/java-mms-spawn.0-9.testprofile | 5 +- java/test-profiles/java-mms.0-10.testprofile | 5 +- java/test-profiles/java-mms.0-8.testprofile | 5 +- java/test-profiles/java-mms.0-9-1.testprofile | 5 +- java/test-profiles/java-mms.0-9.testprofile | 5 +- java/test-profiles/testprofile.defaults | 13 +- 1140 files changed, 61152 insertions(+), 49657 deletions(-) create mode 100644 java/amqp-1-0-client-jms/example/build.xml create mode 100644 java/amqp-1-0-client-jms/resources/LICENSE create mode 100644 java/amqp-1-0-client-jms/resources/NOTICE create mode 100644 java/amqp-1-0-client-jms/resources/README.txt create mode 100644 java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DecodedDestination.java create mode 100644 java/amqp-1-0-client/example/build.xml create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Command.java create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Demo.java create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Receive.java create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Request.java create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Send.java create mode 100644 java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Util.java create mode 100644 java/amqp-1-0-client/resources/LICENSE create mode 100644 java/amqp-1-0-client/resources/NOTICE create mode 100644 java/amqp-1-0-client/resources/README.txt delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Command.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Demo.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/ReadBytes.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receive.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Request.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Send.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SendBytes.java delete mode 100644 java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Util.java create mode 100644 java/amqp-1-0-common/resources/LICENSE create mode 100644 java/amqp-1-0-common/resources/NOTICE create mode 100644 java/amqp-1-0-common/resources/README.txt delete mode 100644 java/bdbstore/jmx/MANIFEST.MF create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreFactory.java create mode 100644 java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java create mode 100644 java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.store.MessageStoreFactory create mode 100644 java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/MessageStoreCreatorTest.java delete mode 100644 java/broker-plugins/access-control/MANIFEST.MF create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclAction.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ClientAction.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AccessControlFirewallException.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRule.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRuleFactory.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRule.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/InetNetwork.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRule.java delete mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java delete mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java delete mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java create mode 100644 java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java create mode 100644 java/broker-plugins/access-control/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AccessControlFactory create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclActionTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclRulePredicatesTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ClientActionTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/RuleTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRuleTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java delete mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java delete mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java delete mode 100644 java/broker-plugins/firewall/MANIFEST.MF delete mode 100644 java/broker-plugins/firewall/build.xml delete mode 100644 java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/config/FirewallException.java delete mode 100644 java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/config/FirewallRule.java delete mode 100644 java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/Firewall.java delete mode 100644 java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/FirewallActivator.java delete mode 100644 java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/FirewallConfiguration.java delete mode 100644 java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java delete mode 100644 java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallPluginTest.java delete mode 100644 java/broker-plugins/management-http/MANIFEST.MF create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementFactory.java delete mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java delete mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java delete mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java delete mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java delete mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogoutServlet.java create mode 100644 java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/session/LoginLogoutReporter.java create mode 100644 java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/index.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js create mode 100644 java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js delete mode 100644 java/broker-plugins/management-http/src/main/java/resources/management.html create mode 100644 java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html create mode 100644 java/broker-plugins/management-http/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PluginFactory create mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementFactoryTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/Asserts.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java delete mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java create mode 100644 java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/session/LoginLogoutReporterTest.java delete mode 100644 java/broker-plugins/management-jmx/MANIFEST.MF create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java delete mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java delete mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementFactory.java delete mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java create mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java delete mode 100644 java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java create mode 100644 java/broker-plugins/management-jmx/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PluginFactory create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/JMXManagementFactoryTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java create mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java delete mode 100644 java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java delete mode 100644 java/broker/etc/config.xml create mode 100644 java/broker/etc/groups delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/CompletionCode.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerResponseCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFClass.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFClassIndicationCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandCompletionCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandDecoder.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandHeader.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFEventClass.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFEventCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFEventSeverity.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFMethod.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodInvocation.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodResponseCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFObjectClass.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFOperation.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFPackage.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageIndicationCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFProperty.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaResponseCommand.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFStatistic.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/qmf/QMFType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfigType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfigType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigType.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreator.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerProperties.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigObjectType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigProperty.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntry.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntryStore.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationManager.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationStoreFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObjectRecoverer.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfigType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigurationPlugin.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/IllegalConfigurationException.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfigType.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/RecovererProvider.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfigType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfigType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfiguration.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfigType.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/XmlConfigurationUtilities.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/AbstractConfiguration.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPluginFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionConfiguration.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionPolicyConfiguration.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionQueueConfiguration.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/KeyStoreRecoverer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PluginRecoverer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PortRecoverer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/RecovererHelper.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/TrustStoreRecoverer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/startup/VirtualHostRecoverer.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStore.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/JsonConfigurationStoreFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/updater/ChangeStateTask.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/updater/CreateChildTask.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/updater/SetAttributeTask.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutor.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeType.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/logging/actors/AbstractManagementActor.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/logging/actors/HttpManagementActor.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingManagementFacade.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/Group.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/GroupMember.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/GroupProvider.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/Plugin.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractPluginAdapter.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugin/AuthenticationManagerFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugin/PluginFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugin/QpidServiceLoader.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugins/Activator.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugins/PluginFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/AbstractPlugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/SecurityPlugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginActivator.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccess.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipal.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/SubjectAuthenticationResult.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/UsernamePrincipal.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractPrincipalDatabaseAuthManagerFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/Base64MD5PasswordFileAuthenticationManagerFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PlainPasswordFileAuthenticationManagerFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupDatabase.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/group/GroupDatabase.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/group/GroupPrincipal.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/security/group/GroupPrincipalAccessor.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java create mode 100644 java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/ConfiguredQueueBindingListener.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostHouseKeepingPlugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostPlugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostPluginFactory.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/logging/SlowConsumerDetection_logmessages.properties delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/logging/TopicDeletePolicy_logmessages.properties delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicy.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyConfiguration.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/slowconsumerdetection/policies/SlowConsumerPolicyPlugin.java delete mode 100644 java/broker/src/main/java/org/apache/qpid/slowconsumerdetection/policies/SlowConsumerPolicyPluginFactory.java create mode 100644 java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.configuration.ConfigurationStoreFactory create mode 100644 java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory create mode 100644 java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ExchangeType create mode 100644 java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.GroupManagerFactory create mode 100644 java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.store.MessageStoreFactory create mode 100644 java/broker/src/main/resources/initial-store.json create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreatorTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerPropertiesTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/plugins/AbstractConfigurationTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/plugins/ConfigurationPluginTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/startup/KeyStoreRecovererTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PluginRecovererTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/configuration/updater/TaskExecutorTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/logging/actors/AbstractManagementActorTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/logging/actors/HttpManagementActorTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingManagementFacadeTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactoryTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/model/configuration/ConfigurationEntryTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/plugins/PluginTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipalTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipalTestHelper.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticationResultTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/TestPrincipalUtils.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/UsernamePrincipalTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/Base64MD5PasswordFileAuthenticationManagerFactoryTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PlainPasswordFileAuthenticationManagerFactoryTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipalTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalUtils.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupDatabaseTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/group/GroupPrincipalAccessorTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/security/group/GroupPrincipalTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreCreatorTest.java create mode 100644 java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionConfigurationTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionPolicyConfigurationTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionQueueConfigurationTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyConfigurationTest.java delete mode 100644 java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java create mode 100644 java/client/example/src/main/java/org/apache/qpid/example/ListReceiver.java create mode 100644 java/client/example/src/main/java/org/apache/qpid/example/ListSender.java create mode 100644 java/client/src/main/java/org/apache/qpid/client/HeartbeatListener.java create mode 100644 java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedListMessage.java create mode 100644 java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedListMessageFactory.java delete mode 100644 java/client/src/main/java/org/apache/qpid/client/protocol/HeartbeatDiagnostics.java create mode 100644 java/client/src/main/java/org/apache/qpid/jms/ListMessage.java create mode 100644 java/client/src/test/java/org/apache/qpid/client/message/AMQPEncodedListMessageUnitTest.java create mode 100644 java/client/src/test/java/org/apache/qpid/client/messaging/address/AddressHelperTest.java create mode 100644 java/client/src/test/java/org/apache/qpid/client/security/DynamicSaslRegistrarTest.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpClass.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpConstant.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpDomain.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpDomainMap.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpField.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpFieldMap.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpMethod.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpModel.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpParseException.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpTemplateException.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpVersion.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/BitFieldGenerateMethod.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/CommandGenerateMethod.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/ConsolidatedField.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/CppGenerator.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/GenerateMethod.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/Generator.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/JavaGenerator.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/LanguageConverter.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/Main.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/MangledGenerateMethod.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/NodeAware.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/Printable.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/SingleVersionClass.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/SingleVersionField.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/SingleVersionMethod.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/SingleVersionModel.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/TargetDirectoryException.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/Utils.java create mode 100644 java/common/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java delete mode 100644 java/common/protocol-version.xml create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/Ticker.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/TransportActivity.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/io/IdleTimeoutTicker.java delete mode 100644 java/common/src/main/java/org/apache/qpid/util/NetMatcher.java create mode 100644 java/common/src/test/java/org/apache/qpid/framing/FieldTableTest.java delete mode 100644 java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java create mode 100644 java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java create mode 100644 java/jca/README-JBOSS-EAP6.txt create mode 100644 java/jca/rar/src/main/resources/META-INF/jboss-ra.xml create mode 100755 java/jca/rar/src/main/resources/META-INF/ra.xml delete mode 100644 java/jca/src/main/resources/META-INF/jboss-ra.xml delete mode 100755 java/jca/src/main/resources/META-INF/ra.xml delete mode 100644 java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ConfigurationManagement.java create mode 100644 java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef delete mode 100644 java/perftests/etc/chartdefs/1001-MessageSize-Transient.chartdef create mode 100644 java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef delete mode 100644 java/perftests/etc/chartdefs/1002-MessageSize-Persistent.chartdef create mode 100644 java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef create mode 100644 java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef create mode 100644 java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef delete mode 100644 java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers.chartdef create mode 100644 java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef delete mode 100644 java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers.chartdef create mode 100644 java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef create mode 100644 java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef create mode 100644 java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef delete mode 100644 java/perftests/etc/chartdefs/1030-BatchSize.chartdef create mode 100644 java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef create mode 100644 java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef create mode 100644 java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef create mode 100644 java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef create mode 100644 java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef create mode 100644 java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef create mode 100644 java/perftests/etc/chartdefs/timeseries/1001-Large-Messages-Transient.chartdef create mode 100644 java/perftests/etc/chartdefs/timeseries/1002-Large-Messages-Persistent.chartdef create mode 100644 java/perftests/etc/chartdefs/timeseries/1011-MultipleProducersAndConsumers-Persistent.chartdef create mode 100644 java/perftests/etc/chartdefs/timeseries/1030-Batch-Size-Small.chartdef create mode 100644 java/perftests/etc/chartdefs/timeseries/1031-Batch-Size-Large.chartdef create mode 100644 java/perftests/etc/chartdefs/timeseries/1040-SortedQueue.chartdef create mode 100755 java/perftests/etc/run-perftests.sh create mode 100644 java/perftests/etc/testdefs/BatchSize.js delete mode 100644 java/perftests/etc/testdefs/BatchSize.json create mode 100644 java/perftests/etc/testdefs/BatchSizeConsumerVaries.js create mode 100644 java/perftests/etc/testdefs/BatchSizeProducerVaries.js create mode 100644 java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js create mode 100644 java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js create mode 100644 java/perftests/etc/testdefs/VaryingNumberOfProducerSessionsSingleConnection.js create mode 100755 java/perftests/etc/visualisation-timeseries.sh create mode 100755 java/perftests/etc/visualisation.sh create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/ResultsFileWriter.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/db/ResultsDbWriter.java delete mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormater.java create mode 100644 java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormatter.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/ResultsFileWriterTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/db/ResultsDbWriterTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/results/ResultsTestFixture.java delete mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java create mode 100644 java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormatterTest.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryStrokeAndPaintApplier.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactory.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesPainter.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesStrokeAndPaintApplier.java delete mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarChartBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesHolder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesLineChartBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/DatasetHolder.java delete mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilder.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGenerator.java delete mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java create mode 100644 java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilderTest.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactoryTest.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesBuilderCallbackTest.java delete mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilderTest.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilderTest.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGeneratorTest.java create mode 100644 java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRowTest.java delete mode 100644 java/systests/etc/config-systests-bdb-settings.xml delete mode 100644 java/systests/etc/config-systests-bdb.xml delete mode 100644 java/systests/etc/config-systests-derby-mem-settings.xml delete mode 100644 java/systests/etc/config-systests-derby-mem.xml delete mode 100644 java/systests/etc/config-systests-derby-settings.xml delete mode 100644 java/systests/etc/config-systests-derby.xml delete mode 100644 java/systests/etc/config-systests-firewall-2.xml delete mode 100644 java/systests/etc/config-systests-firewall-3.xml delete mode 100644 java/systests/etc/config-systests-firewall-settings.xml delete mode 100644 java/systests/etc/config-systests-firewall.xml delete mode 100644 java/systests/etc/config-systests-settings.xml create mode 100644 java/systests/etc/config-systests.json create mode 100644 java/systests/etc/groups-systests create mode 100644 java/systests/src/main/java/org/apache/qpid/client/HeartbeatTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxyTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java create mode 100644 java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/systest/GlobalQueuesTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/systest/GlobalTopicsTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/systest/MergeConfigurationTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/systest/SubscriptionTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/systest/TestingBaseCase.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/systest/TopicTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelper.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelperTest.java mode change 100644 => 100755 java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java delete mode 100644 java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java create mode 100644 java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.java (limited to 'java') diff --git a/java/.gitignore b/java/.gitignore index 417b51f12d..d995501f21 100644 --- a/java/.gitignore +++ b/java/.gitignore @@ -18,3 +18,4 @@ # *.swp eclipse-projects/* +derby.log diff --git a/java/amqp-1-0-client-jms/build.xml b/java/amqp-1-0-client-jms/build.xml index cfc6e0babe..d501be1d8d 100644 --- a/java/amqp-1-0-client-jms/build.xml +++ b/java/amqp-1-0-client-jms/build.xml @@ -24,6 +24,9 @@ + + + diff --git a/java/amqp-1-0-client-jms/example/build.xml b/java/amqp-1-0-client-jms/example/build.xml new file mode 100644 index 0000000000..cb9ab0994c --- /dev/null +++ b/java/amqp-1-0-client-jms/example/build.xml @@ -0,0 +1,28 @@ + + + + + + + + + diff --git a/java/amqp-1-0-client-jms/resources/LICENSE b/java/amqp-1-0-client-jms/resources/LICENSE new file mode 100644 index 0000000000..de4b130f35 --- /dev/null +++ b/java/amqp-1-0-client-jms/resources/LICENSE @@ -0,0 +1,204 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + diff --git a/java/amqp-1-0-client-jms/resources/NOTICE b/java/amqp-1-0-client-jms/resources/NOTICE new file mode 100644 index 0000000000..8d1c3f3122 --- /dev/null +++ b/java/amqp-1-0-client-jms/resources/NOTICE @@ -0,0 +1,5 @@ +Apache Qpid +Copyright 2006-2012 Apache Software Foundation +This product includes software developed at +Apache Software Foundation (http://www.apache.org/) + diff --git a/java/amqp-1-0-client-jms/resources/README.txt b/java/amqp-1-0-client-jms/resources/README.txt new file mode 100644 index 0000000000..35d25050fe --- /dev/null +++ b/java/amqp-1-0-client-jms/resources/README.txt @@ -0,0 +1,7 @@ + +Documentation +-------------- +All of our user documentation can be accessed at: + +http://qpid.apache.org/documentation.html + diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionFactoryImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionFactoryImpl.java index d9e6dfe36d..4856a7c491 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionFactoryImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionFactoryImpl.java @@ -20,8 +20,12 @@ */ package org.apache.qpid.amqp_1_0.jms.impl; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLConnection; +import java.net.URLDecoder; +import java.net.URLStreamHandler; import javax.jms.JMSException; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; @@ -39,6 +43,8 @@ public class ConnectionFactoryImpl implements ConnectionFactory, TopicConnection private String _remoteHost; private boolean _ssl; + private String _queuePrefix; + private String _topicPrefix; public ConnectionFactoryImpl(final String host, final int port, @@ -86,36 +92,70 @@ public class ConnectionFactoryImpl implements ConnectionFactory, TopicConnection public ConnectionImpl createConnection() throws JMSException { - return new ConnectionImpl(_host, _port, _username, _password, _clientId, _remoteHost, _ssl); + return createConnection(_username, _password); } public ConnectionImpl createConnection(final String username, final String password) throws JMSException { - return new ConnectionImpl(_host, _port, username, password, _clientId, _remoteHost, _ssl); + ConnectionImpl connection = new ConnectionImpl(_host, _port, username, password, _clientId, _remoteHost, _ssl); + connection.setQueuePrefix(_queuePrefix); + connection.setTopicPrefix(_topicPrefix); + return connection; } public static ConnectionFactoryImpl createFromURL(final String urlString) throws MalformedURLException { - URL url = new URL(urlString); + URL url = new URL(null, urlString, new URLStreamHandler() + { + @Override + protected URLConnection openConnection(URL u) throws IOException + { + throw new UnsupportedOperationException(); + } + }); + String protocol = url.getProtocol(); + if(protocol == null || "".equals(protocol)) + { + protocol = "amqp"; + } + else if(!protocol.equals("amqp") && !protocol.equals("amqps")) + { + throw new MalformedURLException("Protocol '"+protocol+"' unknown. Must be one of 'amqp' or 'amqps'."); + } String host = url.getHost(); int port = url.getPort(); + + boolean ssl = false; + if(port == -1) { - port = 5672; + if("amqps".equals(protocol)) + { + port = 5671; + ssl = true; + } + else + { + port = 5672; + } } + else if("amqps".equals(protocol)) + { + ssl = true; + } + String userInfo = url.getUserInfo(); String username = null; String password = null; String clientId = null; String remoteHost = null; - boolean ssl = false; if(userInfo != null) { String[] components = userInfo.split(":",2); - username = components[0]; + username = URLDecoder.decode(components[0]); if(components.length == 2) { - password = components[1]; + password = URLDecoder.decode(components[1]); } } String query = url.getQuery(); @@ -139,6 +179,11 @@ public class ConnectionFactoryImpl implements ConnectionFactory, TopicConnection } } + if(remoteHost == null) + { + remoteHost = host; + } + return new ConnectionFactoryImpl(host, port, username, password, clientId, remoteHost, ssl); } @@ -170,4 +215,24 @@ public class ConnectionFactoryImpl implements ConnectionFactory, TopicConnection connection.setTopicConnection(true); return connection; } + + public String getTopicPrefix() + { + return _topicPrefix; + } + + public void setTopicPrefix(String topicPrefix) + { + _topicPrefix = topicPrefix; + } + + public String getQueuePrefix() + { + return _queuePrefix; + } + + public void setQueuePrefix(String queuePrefix) + { + _queuePrefix = queuePrefix; + } } diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionImpl.java index 587b12b51a..be1c2d6514 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionImpl.java @@ -25,9 +25,8 @@ import org.apache.qpid.amqp_1_0.transport.Container; import javax.jms.*; import javax.jms.IllegalStateException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; +import javax.jms.Queue; +import java.util.*; public class ConnectionImpl implements Connection, QueueConnection, TopicConnection { @@ -43,16 +42,26 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect private boolean _isQueueConnection; private boolean _isTopicConnection; private final Collection _closeTasks = new ArrayList(); + private final String _host; + private final int _port; + private final String _username; + private final String _password; + private final String _remoteHost; + private final boolean _ssl; + private String _clientId; + private String _queuePrefix; + private String _topicPrefix; private static enum State { + UNCONNECTED, STOPPED, STARTED, CLOSED } - private volatile State _state = State.STOPPED; + private volatile State _state = State.UNCONNECTED; public ConnectionImpl(String host, int port, String username, String password, String clientId) throws JMSException { @@ -66,20 +75,52 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect public ConnectionImpl(String host, int port, String username, String password, String clientId, String remoteHost, boolean ssl) throws JMSException { - Container container = clientId == null ? new Container() : new Container(clientId); - // TODO - authentication, containerId, clientId, ssl?, etc - try + _host = host; + _port = port; + _username = username; + _password = password; + _clientId = clientId; + _remoteHost = remoteHost; + _ssl = ssl; + } + + private void connect() throws JMSException + { + synchronized(_lock) { - _conn = new org.apache.qpid.amqp_1_0.client.Connection(host, port, username, password, container, remoteHost, ssl); - // TODO - retrieve negotiated AMQP version - _connectionMetaData = new ConnectionMetaDataImpl(1,0,0); + // already connected? + if( _state == State.UNCONNECTED ) + { + _state = State.STOPPED; + + Container container = _clientId == null ? new Container() : new Container(_clientId); + // TODO - authentication, containerId, clientId, ssl?, etc + try + { + _conn = new org.apache.qpid.amqp_1_0.client.Connection(_host, + _port, _username, _password, container, _remoteHost, _ssl); + // TODO - retrieve negotiated AMQP version + _connectionMetaData = new ConnectionMetaDataImpl(1,0,0); + } + catch (org.apache.qpid.amqp_1_0.client.Connection.ConnectionException e) + { + JMSException jmsEx = new JMSException(e.getMessage()); + jmsEx.setLinkedException(e); + jmsEx.initCause(e); + throw jmsEx; + } + } } - catch (org.apache.qpid.amqp_1_0.client.Connection.ConnectionException e) + } + + private void checkNotConnected(String msg) throws IllegalStateException + { + synchronized(_lock) { - JMSException jmsEx = new JMSException(e.getMessage()); - jmsEx.setLinkedException(e); - jmsEx.initCause(e); - throw jmsEx; + if( _state != State.UNCONNECTED ) + { + throw new IllegalStateException(msg); + } } } @@ -111,7 +152,7 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect { throw new IllegalStateException("Cannot create a session on a closed connection"); } - + connect(); SessionImpl session = new SessionImpl(this, acknowledgeMode); session.setQueueSession(_isQueueConnection); session.setTopicSession(_isTopicConnection); @@ -125,14 +166,19 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect public String getClientID() throws JMSException { checkClosed(); - return _conn.getEndpoint().getContainer().getId(); + return _clientId; } - public void setClientID(final String s) throws JMSException + public void setClientID(final String value) throws JMSException { - throw new IllegalStateException("Cannot set client-id to \"" - + s - + "\"; client-id must be set on connection creation"); + checkNotConnected("Cannot set client-id to \"" + + value + + "\"; client-id must be set before the connection is used"); + if( _clientId !=null ) + { + throw new IllegalStateException("client-id has already been set"); + } + _clientId = value; } public ConnectionMetaData getMetaData() throws JMSException @@ -158,6 +204,7 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect synchronized(_lock) { checkClosed(); + connect(); if(_state == State.STOPPED) { // TODO @@ -187,6 +234,7 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect { session.stop(); } + case UNCONNECTED: _state = State.STOPPED; break; case CLOSED: @@ -235,7 +283,9 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect { task.onClose(); } - _conn.close(); + if(_conn != null && _state != State.UNCONNECTED ) { + _conn.close(); + } _state = State.CLOSED; } @@ -282,6 +332,10 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect final int i) throws JMSException { checkClosed(); + if (_isQueueConnection) + { + throw new IllegalStateException("QueueConnection cannot be used to create Pub/Sub based resources."); + } return null; //TODO } @@ -326,4 +380,78 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect { _isTopicConnection = topicConnection; } + + public String getTopicPrefix() + { + return _topicPrefix; + } + + public void setTopicPrefix(String topicPrefix) + { + _topicPrefix = topicPrefix; + } + + public String getQueuePrefix() + { + return _queuePrefix; + } + + public void setQueuePrefix(String queueprefix) + { + _queuePrefix = queueprefix; + } + + DecodedDestination toDecodedDestination(DestinationImpl dest) + { + String address = dest.getAddress(); + Set kind = null; + Class clazz = dest.getClass(); + if( clazz==QueueImpl.class ) + { + kind = MessageImpl.JMS_QUEUE_ATTRIBUTES; + if( _queuePrefix!=null ) + { + // Avoid double prefixing.. + if( !address.startsWith(_queuePrefix) ) + { + address = _queuePrefix+address; + } + } + } + else if( clazz==TopicImpl.class ) + { + kind = MessageImpl.JMS_TOPIC_ATTRIBUTES; + if( _topicPrefix!=null ) + { + // Avoid double prefixing.. + if( !address.startsWith(_topicPrefix) ) + { + address = _topicPrefix+address; + } + } + } + else if( clazz==TemporaryQueueImpl.class ) + { + kind = MessageImpl.JMS_TEMP_QUEUE_ATTRIBUTES; + } + else if( clazz==TemporaryTopicImpl.class ) + { + kind = MessageImpl.JMS_TEMP_TOPIC_ATTRIBUTES; + } + return new DecodedDestination(address, kind); + } + + DecodedDestination toDecodedDestination(String address, Set kind) + { + if( (kind == null || kind.equals(MessageImpl.JMS_QUEUE_ATTRIBUTES)) && _queuePrefix!=null && address.startsWith(_queuePrefix)) + { + return new DecodedDestination(address.substring(_queuePrefix.length()), MessageImpl.JMS_QUEUE_ATTRIBUTES); + } + if( (kind == null || kind.equals(MessageImpl.JMS_TOPIC_ATTRIBUTES)) && _topicPrefix!=null && address.startsWith(_topicPrefix)) + { + return new DecodedDestination(address.substring(_topicPrefix.length()), MessageImpl.JMS_TOPIC_ATTRIBUTES); + } + return new DecodedDestination(address, kind); + } + } diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DecodedDestination.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DecodedDestination.java new file mode 100644 index 0000000000..74e98c2163 --- /dev/null +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DecodedDestination.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.qpid.amqp_1_0.jms.impl; + +import java.util.Set; + +/** +* @author Hiram Chirino +*/ +class DecodedDestination +{ + private final String _address; + private final Set _attributes; + + DecodedDestination(String address, Set kind) + { + _address = address; + _attributes = kind; + } + + public String getAddress() + { + return _address; + } + + public Set getAttributes() + { + return _attributes; + } +} diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java index e0402cd0a7..3c15c74d6f 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java @@ -127,7 +127,7 @@ public class MessageConsumerImpl implements MessageConsumer, QueueReceiver, Topi { try { - return _session.getClientSession(). createReceiver(_destination.getAddress(), AcknowledgeMode.ALO, + return _session.getClientSession(). createReceiver(_session.toAddress(_destination), AcknowledgeMode.ALO, _linkName, _durable, getFilters(), null); } catch (AmqpErrorException e) @@ -316,9 +316,9 @@ public class MessageConsumerImpl implements MessageConsumer, QueueReceiver, Topi _lastUnackedMessage = deliveryTag; } - void preReceiveAction(final org.apache.qpid.amqp_1_0.client.Message msg) throws IllegalStateException + void preReceiveAction(final org.apache.qpid.amqp_1_0.client.Message msg) { - final int acknowledgeMode = _session.getAcknowledgeMode(); + int acknowledgeMode = _session.getAckModeEnum().ordinal(); if(acknowledgeMode == Session.AUTO_ACKNOWLEDGE || acknowledgeMode == Session.DUPS_OK_ACKNOWLEDGE diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java index f1056b94fd..fba50c5477 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java @@ -50,14 +50,24 @@ public abstract class MessageImpl implements Message static final Set _supportedClasses = new HashSet(Arrays.asList(Boolean.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Character.class, String.class, byte[].class)); - private static final Symbol JMS_TYPE = Symbol.valueOf("x-opt-jms-type"); + static final Symbol JMS_TYPE = Symbol.valueOf("x-opt-jms-type"); + static final Symbol TO_TYPE = Symbol.valueOf("x-opt-to-type"); + static final Symbol REPLY_TO_TYPE = Symbol.valueOf("x-opt-reply-type"); + + static final String QUEUE_ATTRIBUTE = "queue"; + static final String TOPIC_ATTRIBUTE = "topic"; + static final String TEMPORARY_ATTRIBUTE = "temporary"; + + static final Set JMS_QUEUE_ATTRIBUTES = set(QUEUE_ATTRIBUTE); + static final Set JMS_TOPIC_ATTRIBUTES = set(TOPIC_ATTRIBUTE); + static final Set JMS_TEMP_QUEUE_ATTRIBUTES = set(QUEUE_ATTRIBUTE, TEMPORARY_ATTRIBUTE); + static final Set JMS_TEMP_TOPIC_ATTRIBUTES = set(TOPIC_ATTRIBUTE, TEMPORARY_ATTRIBUTE); private Header _header; private Properties _properties; private ApplicationProperties _applicationProperties; private Footer _footer; - public static final Charset UTF_8_CHARSET = Charset.forName("UTF-8"); - private SessionImpl _sessionImpl; + private final SessionImpl _sessionImpl; private boolean _readOnly; private MessageAnnotations _messageAnnotations; @@ -171,45 +181,53 @@ public abstract class MessageImpl implements Message public DestinationImpl getJMSReplyTo() throws JMSException { - return DestinationImpl.valueOf(getReplyTo()); + return toDestination(getReplyTo(), splitCommaSeparateSet((String) getMessageAnnotation(REPLY_TO_TYPE))); } public void setJMSReplyTo(Destination destination) throws NonAMQPDestinationException { - if(destination == null) + if( destination==null ) { setReplyTo(null); - } - else if (destination instanceof org.apache.qpid.amqp_1_0.jms.Destination) - { - setReplyTo(((org.apache.qpid.amqp_1_0.jms.Destination)destination).getAddress()); + messageAnnotationMap().remove(REPLY_TO_TYPE); } else { - throw new NonAMQPDestinationException(destination); + DecodedDestination dd = toDecodedDestination(destination); + setReplyTo(dd.getAddress()); + messageAnnotationMap().put(REPLY_TO_TYPE, join(",", dd.getAttributes())); } } public DestinationImpl getJMSDestination() throws JMSException { - return _isFromQueue ? QueueImpl.valueOf(getTo()) - : _isFromTopic ? TopicImpl.valueOf(getTo()) - : DestinationImpl.valueOf(getTo()); + Set type = splitCommaSeparateSet((String) getMessageAnnotation(TO_TYPE)); + if( type==null ) + { + if( _isFromQueue ) + { + type = JMS_QUEUE_ATTRIBUTES; + } + else if( _isFromTopic ) + { + type = JMS_TOPIC_ATTRIBUTES; + } + } + return toDestination(getTo(), type); } public void setJMSDestination(Destination destination) throws NonAMQPDestinationException { - if(destination == null) + if( destination==null ) { setTo(null); - } - else if (destination instanceof org.apache.qpid.amqp_1_0.jms.Destination) - { - setTo(((org.apache.qpid.amqp_1_0.jms.Destination)destination).getAddress()); + messageAnnotationMap().remove(TO_TYPE); } else { - throw new NonAMQPDestinationException(destination); + DecodedDestination dd = toDecodedDestination(destination); + setTo(dd.getAddress()); + messageAnnotationMap().put(TO_TYPE, join(",", dd.getAttributes())); } } @@ -264,22 +282,13 @@ public abstract class MessageImpl implements Message public String getJMSType() throws JMSException { - Map messageAttrs = _messageAnnotations == null ? null : _messageAnnotations.getValue(); - final Object attrValue = messageAttrs == null ? null : messageAttrs.get(JMS_TYPE); - + final Object attrValue = getMessageAnnotation(JMS_TYPE); return attrValue instanceof String ? attrValue.toString() : null; } public void setJMSType(String s) throws JMSException { - Map messageAttrs = _messageAnnotations == null ? null : _messageAnnotations.getValue(); - if(messageAttrs == null) - { - messageAttrs = new HashMap(); - _messageAnnotations = new MessageAnnotations(messageAttrs); - } - - messageAttrs.put(JMS_TYPE, s); + messageAnnotationMap().put(JMS_TYPE, s); } public long getJMSExpiration() throws JMSException @@ -1206,4 +1215,118 @@ public abstract class MessageImpl implements Message } abstract Collection
getSections(); + + DecodedDestination toDecodedDestination(Destination destination) throws NonAMQPDestinationException + { + if(destination == null) + { + return null; + } + if (destination instanceof DestinationImpl) + { + return _sessionImpl.getConnection().toDecodedDestination((DestinationImpl) destination); + } + throw new NonAMQPDestinationException(destination); + } + + DestinationImpl toDestination(String address, Set kind) + { + if( address == null ) + { + return null; + } + + // If destination prefixes are in play, we have to strip the the prefix, and we might + // be able to infer the kind, if we don't know it yet. + DecodedDestination decoded = _sessionImpl.getConnection().toDecodedDestination(address, kind); + address = decoded.getAddress(); + kind = decoded.getAttributes(); + + if( kind == null ) + { + return DestinationImpl.valueOf(address); + } + if( kind.contains(QUEUE_ATTRIBUTE) ) + { + if( kind.contains(TEMPORARY_ATTRIBUTE) ) + { + return new TemporaryQueueImpl(address, null, _sessionImpl); + } + else + { + return QueueImpl.valueOf(address); + } + } + else if ( kind.contains(TOPIC_ATTRIBUTE) ) + { + if( kind.contains(TEMPORARY_ATTRIBUTE) ) + { + return new TemporaryTopicImpl(address, null, _sessionImpl); + } + else + { + return TopicImpl.valueOf(address); + } + } + + return DestinationImpl.valueOf(address); + } + + private Object getMessageAnnotation(Symbol key) + { + Map messageAttrs = _messageAnnotations == null ? null : _messageAnnotations.getValue(); + return messageAttrs == null ? null : messageAttrs.get(key); + } + + private Map messageAnnotationMap() + { + Map messageAttrs = _messageAnnotations == null ? null : _messageAnnotations.getValue(); + if(messageAttrs == null) + { + messageAttrs = new HashMap(); + _messageAnnotations = new MessageAnnotations(messageAttrs); + } + return messageAttrs; + } + + Set splitCommaSeparateSet(String value) + { + if( value == null ) + { + return null; + } + HashSet rc = new HashSet(); + for( String x: value.split("\\s*,\\s*") ) + { + rc.add(x); + } + return rc; + } + + private static Set set(String ...args) + { + HashSet s = new HashSet(); + for (String arg : args) + { + s.add(arg); + } + return Collections.unmodifiableSet(s); + } + + static final String join(String sep, Iterable items) + { + StringBuilder result = new StringBuilder(); + + for (Object o : items) + { + if (result.length() > 0) + { + result.append(sep); + } + result.append(o.toString()); + } + + return result.toString(); + } + } diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java index 5bb8845eb7..badc20472b 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java @@ -20,7 +20,6 @@ package org.apache.qpid.amqp_1_0.jms.impl; import org.apache.qpid.amqp_1_0.client.Sender; import org.apache.qpid.amqp_1_0.jms.MessageProducer; -import org.apache.qpid.amqp_1_0.jms.Queue; import org.apache.qpid.amqp_1_0.jms.QueueSender; import org.apache.qpid.amqp_1_0.jms.TemporaryDestination; import org.apache.qpid.amqp_1_0.jms.TopicPublisher; @@ -61,7 +60,7 @@ public class MessageProducerImpl implements MessageProducer, QueueSender, TopicP { try { - _sender = _session.getClientSession().createSender(_destination.getAddress()); + _sender = _session.getClientSession().createSender(_session.toAddress(_destination)); } catch (Sender.SenderCreationException e) { @@ -297,7 +296,7 @@ public class MessageProducerImpl implements MessageProducer, QueueSender, TopicP try { _destination = (DestinationImpl) destination; - _sender = _session.getClientSession().createSender(_destination.getAddress()); + _sender = _session.getClientSession().createSender(_session.toAddress(_destination)); send(message, deliveryMode, priority, ttl); diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ObjectMessageImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ObjectMessageImpl.java index 2a52b0557a..95c1497d07 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ObjectMessageImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ObjectMessageImpl.java @@ -40,7 +40,25 @@ public class ObjectMessageImpl extends MessageImpl implements ObjectMessage { static final Symbol CONTENT_TYPE = Symbol.valueOf("application/x-java-serialized-object"); - private Data _objectData; + static final Data NULL_OBJECT_DATA; + static + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try + { + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(null); + oos.flush(); + oos.close(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + NULL_OBJECT_DATA = new Data(new Binary(baos.toByteArray())); + } + + private Data _objectData = NULL_OBJECT_DATA; protected ObjectMessageImpl(Header header, MessageAnnotations messageAnnotations, diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueBrowserImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueBrowserImpl.java index 527e82eaed..8fab315b10 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueBrowserImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueBrowserImpl.java @@ -18,9 +18,7 @@ */ package org.apache.qpid.amqp_1_0.jms.impl; -import java.util.Collections; -import java.util.Enumeration; -import java.util.Map; +import java.util.*; import javax.jms.InvalidSelectorException; import javax.jms.JMSException; import org.apache.qpid.amqp_1_0.client.AcknowledgeMode; @@ -29,6 +27,7 @@ import org.apache.qpid.amqp_1_0.client.Receiver; import org.apache.qpid.amqp_1_0.jms.QueueBrowser; import org.apache.qpid.amqp_1_0.type.AmqpErrorException; import org.apache.qpid.amqp_1_0.type.Symbol; +import org.apache.qpid.amqp_1_0.type.UnsignedInteger; import org.apache.qpid.amqp_1_0.type.messaging.Filter; import org.apache.qpid.amqp_1_0.type.messaging.JMSSelectorFilter; import org.apache.qpid.amqp_1_0.type.messaging.StdDistMode; @@ -39,49 +38,27 @@ public class QueueBrowserImpl implements QueueBrowser private static final String JMS_SELECTOR = "jms-selector"; private QueueImpl _queue; private String _selector; - private Receiver _receiver; - private Message _nextElement; - private MessageEnumeration _enumeration; + private final SessionImpl _session; + private Map _filters; + private HashSet _enumerations = new HashSet(); + private boolean _closed; QueueBrowserImpl(final QueueImpl queue, final String selector, SessionImpl session) throws JMSException { _queue = queue; _selector = selector; + _session = session; - Map filters; if(selector == null || selector.trim().equals("")) { - filters = null; + _filters = null; } else { - filters = Collections.singletonMap(Symbol.valueOf(JMS_SELECTOR),(Filter) new JMSSelectorFilter(_selector)); - } - - - try - { - _receiver = session.getClientSession().createReceiver(queue.getAddress(), - StdDistMode.COPY, - AcknowledgeMode.AMO,null, - false, - filters, null); - _nextElement = _receiver.receive(0L); - _enumeration = new MessageEnumeration(); - } - catch(AmqpErrorException e) - { - org.apache.qpid.amqp_1_0.type.transport.Error error = e.getError(); - if(AmqpError.INVALID_FIELD.equals(error.getCondition())) - { - throw new InvalidSelectorException(e.getMessage()); - } - else - { - throw new JMSException(e.getMessage(), error.getCondition().getValue().toString()); - } - + _filters = Collections.singletonMap(Symbol.valueOf(JMS_SELECTOR),(Filter) new JMSSelectorFilter(_selector)); + // We do this just to have the server validate the filter.. + new MessageEnumeration().close(); } } @@ -97,42 +74,124 @@ public class QueueBrowserImpl implements QueueBrowser public Enumeration getEnumeration() throws JMSException { - if(_enumeration == null) + if(_closed) { throw new IllegalStateException("Browser has been closed"); } - return _enumeration; + return new MessageEnumeration(); } public void close() throws JMSException { - _receiver.close(); - _enumeration = null; + _closed = true; + for(MessageEnumeration me : new ArrayList(_enumerations)) + { + me.close(); + } } - private final class MessageEnumeration implements Enumeration + private final class MessageEnumeration implements Enumeration { + private Receiver _receiver; + private MessageImpl _nextElement; + private boolean _needNext = true; + + MessageEnumeration() throws JMSException + { + try + { + _receiver = _session.getClientSession().createReceiver(_session.toAddress(_queue), + StdDistMode.COPY, + AcknowledgeMode.AMO, null, + false, + _filters, null); + _receiver.setCredit(UnsignedInteger.valueOf(100), true); + } + catch(AmqpErrorException e) + { + org.apache.qpid.amqp_1_0.type.transport.Error error = e.getError(); + if(AmqpError.INVALID_FIELD.equals(error.getCondition())) + { + throw new InvalidSelectorException(e.getMessage()); + } + else + { + throw new JMSException(e.getMessage(), error.getCondition().getValue().toString()); + } + + } + _enumerations.add(this); + + } + + public void close() + { + _enumerations.remove(this); + _receiver.close(); + _receiver = null; + } @Override public boolean hasMoreElements() { + if( _receiver == null ) + { + return false; + } + if( _needNext ) + { + _needNext = false; + _nextElement = createJMSMessage(_receiver.receive(0L)); + if( _nextElement == null ) + { + // Drain to verify there really are no more messages. + _receiver.drain(); + _receiver.drainWait(); + _nextElement = createJMSMessage(_receiver.receive(0L)); + if( _nextElement == null ) + { + close(); + } + else + { + // there are still more messages, open up the credit window again.. + _receiver.clearDrain(); + } + } + } return _nextElement != null; } @Override - public Message nextElement() + public MessageImpl nextElement() { - - Message message = _nextElement; - if(message == null) + if( hasMoreElements() ) { - message = _receiver.receive(0l); + MessageImpl message = _nextElement; + _nextElement = null; + _needNext = true; + return message; } - if(message != null) + else { - _nextElement = _receiver.receive(0l); + throw new NoSuchElementException(); } + } + } + + MessageImpl createJMSMessage(final Message msg) + { + if(msg != null) + { + final MessageImpl message = _session.getMessageFactory().createMessage(_queue, msg); + message.setFromQueue(true); + message.setFromTopic(false); return message; } + else + { + return null; + } } + } diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java index d46ed7183f..67b597f5cf 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java @@ -41,7 +41,7 @@ public class QueueReceiverImpl extends MessageConsumerImpl implements QueueRecei { try { - return getSession().getClientSession().createMovingReceiver(getDestination().getAddress()); + return getSession().getClientSession().createMovingReceiver(getSession().toAddress(getDestination())); } catch (AmqpErrorException e) { diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java index e321245a0e..58b7d4f625 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java @@ -766,7 +766,7 @@ public class SessionImpl implements Session, QueueSession, TopicSession { while(!_closed) { - while(!_started || (_recoveredMessage == null && _messageConsumerList.isEmpty())) + while(!_closed && (!_started || (_recoveredMessage == null && _messageConsumerList.isEmpty()))) { try { @@ -777,7 +777,7 @@ public class SessionImpl implements Session, QueueSession, TopicSession return; } } - while(_started && (_recoveredMessage != null || !_messageConsumerList.isEmpty())) + while(!_closed && (_started && (_recoveredMessage != null || !_messageConsumerList.isEmpty()))) { Message msg; @@ -804,6 +804,10 @@ public class SessionImpl implements Session, QueueSession, TopicSession if(message != null) { + if(_acknowledgeMode == AcknowledgeMode.CLIENT_ACKNOWLEDGE) + { + consumer.setLastUnackedMessage(msg.getDeliveryTag()); + } _currentConsumer = consumer; _currentMessage = msg; try @@ -816,11 +820,11 @@ public class SessionImpl implements Session, QueueSession, TopicSession _currentMessage = null; } - if((_recoveredMessage == null) && (_acknowledgeMode == AcknowledgeMode.AUTO_ACKNOWLEDGE - || _acknowledgeMode == AcknowledgeMode.DUPS_OK_ACKNOWLEDGE)) + if(_recoveredMessage == null) { - consumer.acknowledge(msg); + consumer.preReceiveAction(msg); } + } } @@ -895,4 +899,10 @@ public class SessionImpl implements Session, QueueSession, TopicSession { _isTopicSession = topicSession; } + + String toAddress(DestinationImpl dest) + { + return _connection.toDecodedDestination(dest).getAddress(); + } + } diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java index 52d8c412ec..f267794796 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java @@ -66,7 +66,7 @@ public class TopicSubscriberImpl extends MessageConsumerImpl implements TopicSub { try { - String address = getDestination().getAddress(); + String address = getSession().toAddress(getDestination()); Receiver receiver = getSession().getClientSession().createReceiver(address, StdDistMode.COPY, AcknowledgeMode.ALO, getLinkName(), isDurable(), getFilters(), diff --git a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/jndi/PropertiesFileInitialContextFactory.java b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/jndi/PropertiesFileInitialContextFactory.java index 31030a7d30..091ab41304 100644 --- a/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/jndi/PropertiesFileInitialContextFactory.java +++ b/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/jndi/PropertiesFileInitialContextFactory.java @@ -57,6 +57,9 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor Map data = new ConcurrentHashMap(); String file = null; + String fileName = (environment.containsKey(Context.PROVIDER_URL)) + ? (String)environment.get(Context.PROVIDER_URL) : System.getProperty(Context.PROVIDER_URL); + try { diff --git a/java/amqp-1-0-client/build.xml b/java/amqp-1-0-client/build.xml index 031809a380..cd7654ed15 100644 --- a/java/amqp-1-0-client/build.xml +++ b/java/amqp-1-0-client/build.xml @@ -23,6 +23,9 @@ + + + diff --git a/java/amqp-1-0-client/example/build.xml b/java/amqp-1-0-client/example/build.xml new file mode 100644 index 0000000000..89bba729dd --- /dev/null +++ b/java/amqp-1-0-client/example/build.xml @@ -0,0 +1,28 @@ + + + + + + + + + diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Command.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Command.java new file mode 100644 index 0000000000..3bb26744c4 --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Command.java @@ -0,0 +1,43 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.amqp_1_0.client; + +import java.lang.reflect.InvocationTargetException; + +public class Command +{ + public static void main(String[] args) throws + ClassNotFoundException, + NoSuchMethodException, + InvocationTargetException, + IllegalAccessException, + InstantiationException + { + String name = args[0]; + String[] cmdArgs = new String[args.length-1]; + System.arraycopy(args,1,cmdArgs,0,args.length-1); + name = "org.apache.qpid.amqp_1_0.client." + String.valueOf(name.charAt(0)).toUpperCase() + name.substring(1).toLowerCase(); + Class clazz = (Class) Class.forName(name); + Util util = clazz.getDeclaredConstructor(String[].class).newInstance((Object)cmdArgs); + util.run(); + + } +} diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Demo.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Demo.java new file mode 100644 index 0000000000..b58ce6bfe5 --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Demo.java @@ -0,0 +1,407 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.amqp_1_0.client; + +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; +import org.apache.qpid.amqp_1_0.type.AmqpErrorException; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.UnsignedInteger; +import org.apache.qpid.amqp_1_0.type.UnsignedLong; +import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; +import org.apache.qpid.amqp_1_0.type.messaging.ApplicationProperties; +import org.apache.qpid.amqp_1_0.type.messaging.Header; +import org.apache.qpid.amqp_1_0.type.messaging.Properties; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Demo extends Util +{ + private static final String USAGE_STRING = "demo [options] [ ...]\n\nOptions:"; + private static final String OPCODE = "opcode"; + private static final String ACTION = "action"; + private static final String MESSAGE_ID = "message-id"; + private static final String VENDOR = "vendor"; + private static final String LOG = "log"; + private static final String RECEIVED = "received"; + private static final String TEST = "test"; + private static final String APACHE = "apache"; + private static final String SENT = "sent"; + private static final String LINK_REF = "link-ref"; + private static final String HOST = "host"; + private static final String PORT = "port"; + private static final String SASL_USER = "sasl-user"; + private static final String SASL_PASSWORD = "sasl-password"; + private static final String ROLE = "role"; + private static final String ADDRESS = "address"; + private static final String SENDER = "sender"; + private static final String SEND_MESSAGE = "send-message"; + private static final String ANNOUNCE = "announce"; + private static final String MESSAGE_VENDOR = "message-vendor"; + private static final String CREATE_LINK = "create-link"; + + public static void main(String[] args) + { + new Demo(args).run(); + } + + public Demo(String[] args) + { + super(args); + } + + @Override + protected boolean hasLinkDurableOption() + { + return false; + } + + @Override + protected boolean hasLinkNameOption() + { + return false; + } + + @Override + protected boolean hasResponseQueueOption() + { + return false; + } + + @Override + protected boolean hasSizeOption() + { + return false; + } + + @Override + protected boolean hasBlockOption() + { + return false; + } + + @Override + protected boolean hasStdInOption() + { + return false; + } + + @Override + protected boolean hasTxnOption() + { + return false; + } + + @Override + protected boolean hasModeOption() + { + return true; + } + + @Override + protected boolean hasCountOption() + { + return false; + } + + @Override + protected boolean hasWindowSizeOption() + { + return false; + } + + public void run() + { + + try + { + + final String vendor = getArgs()[0]; + final String queue = "control"; + + String message = ""; + + Connection conn = newConnection(); + Session session = conn.createSession(); + + + Receiver responseReceiver; + + responseReceiver = session.createTemporaryQueueReceiver(); + + + + + responseReceiver.setCredit(UnsignedInteger.valueOf(getWindowSize()), true); + + + + Sender s = session.createSender(queue, getWindowSize(), getMode()); + + + Properties properties = new Properties(); + properties.setMessageId(java.util.UUID.randomUUID()); + properties.setReplyTo(responseReceiver.getAddress()); + + HashMap appPropMap = new HashMap(); + ApplicationProperties appProperties = new ApplicationProperties(appPropMap); + + appPropMap.put(OPCODE, ANNOUNCE); + appPropMap.put(VENDOR, vendor); + appPropMap.put(ADDRESS,responseReceiver.getAddress()); + + AmqpValue amqpValue = new AmqpValue(message); + Section[] sections = { properties, appProperties, amqpValue}; + final Message message1 = new Message(Arrays.asList(sections)); + + s.send(message1); + + Map sendingLinks = new HashMap(); + Map receivingLinks = new HashMap(); + + + boolean done = false; + + while(!done) + { + boolean wait = true; + Message m = responseReceiver.receive(false); + if(m != null) + { + List
payload = m.getPayload(); + wait = false; + ApplicationProperties props = m.getApplicationProperties(); + Map map = props.getValue(); + String op = (String) map.get(OPCODE); + if("reset".equals(op)) + { + for(Sender sender : sendingLinks.values()) + { + try + { + sender.close(); + Session session1 = sender.getSession(); + session1.close(); + session1.getConnection().close(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + for(Receiver receiver : receivingLinks.values()) + { + try + { + receiver.close(); + receiver.getSession().close(); + receiver.getSession().getConnection().close(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + sendingLinks.clear(); + receivingLinks.clear(); + } + else if(CREATE_LINK.equals(op)) + { + Object linkRef = map.get(LINK_REF); + String host = (String) map.get(HOST); + Object o = map.get(PORT); + int port = Integer.parseInt(String.valueOf(o)); + String user = (String) map.get(SASL_USER); + String password = (String) map.get(SASL_PASSWORD); + String role = (String) map.get(ROLE); + String address = (String) map.get(ADDRESS); + System.err.println("Host: " + host + "\tPort: " + port + "\t user: " + user +"\t password: " + password); + try{ + + + Connection conn2 = new Connection(host, port, user, password, host); + Session session2 = conn2.createSession(); + if(sendingLinks.containsKey(linkRef)) + { + try + { + sendingLinks.remove(linkRef).close(); + } + catch (Exception e) + { + + } + } + if(receivingLinks.containsKey(linkRef)) + { + try + { + receivingLinks.remove(linkRef).close(); + } + catch (Exception e) + { + + } + } + if(SENDER.equals(role)) + { + + System.err.println("%%% Creating sender (" + linkRef + ")"); + Sender sender = session2.createSender(address); + sendingLinks.put(linkRef, sender); + } + else + { + + System.err.println("%%% Creating receiver (" + linkRef + ")"); + Receiver receiver2 = session2.createReceiver(address); + receiver2.setCredit(UnsignedInteger.valueOf(getWindowSize()), true); + + receivingLinks.put(linkRef, receiver2); + } + } + catch(Exception e) + { + e.printStackTrace(); + } + } + else if(SEND_MESSAGE.equals(op)) + { + Sender sender = sendingLinks.get(map.get(LINK_REF)); + Properties m2props = new Properties(); + Object messageId = map.get(MESSAGE_ID); + m2props.setMessageId(messageId); + Map m2propmap = new HashMap(); + m2propmap.put(OPCODE, TEST); + m2propmap.put(VENDOR, vendor); + ApplicationProperties m2appProps = new ApplicationProperties(m2propmap); + Message m2 = new Message(Arrays.asList(m2props, m2appProps, new AmqpValue("AMQP-"+messageId))); + sender.send(m2); + + Map m3propmap = new HashMap(); + m3propmap.put(OPCODE, LOG); + m3propmap.put(ACTION, SENT); + m3propmap.put(MESSAGE_ID, messageId); + m3propmap.put(VENDOR, vendor); + m3propmap.put(MESSAGE_VENDOR, vendor); + + + Message m3 = new Message(Arrays.asList(new ApplicationProperties(m3propmap), + new AmqpValue("AMQP-"+messageId))); + s.send(m3); + + } + + responseReceiver.acknowledge(m); + } + else + { + for(Map.Entry entry : receivingLinks.entrySet()) + { + m = entry.getValue().receive(false); + if(m != null) + { + wait = false; + + System.err.println("%%% Received message from " + entry.getKey()); + + Properties mp = m.getProperties(); + ApplicationProperties ap = m.getApplicationProperties(); + + Map m3propmap = new HashMap(); + m3propmap.put(OPCODE, LOG); + m3propmap.put(ACTION, RECEIVED); + m3propmap.put(MESSAGE_ID, mp.getMessageId()); + m3propmap.put(VENDOR, vendor); + m3propmap.put(MESSAGE_VENDOR, ap.getValue().get(VENDOR)); + + Message m3 = new Message(Arrays.asList(new ApplicationProperties(m3propmap), + new AmqpValue("AMQP-"+mp.getMessageId()))); + s.send(m3); + + entry.getValue().acknowledge(m); + } + + } + } + + if(wait) + { + try + { + Thread.sleep(500l); + } + catch (InterruptedException e) + { + e.printStackTrace(); //TODO. + } + } + + } + + + + + + + + + + s.close(); + session.close(); + conn.close(); + + } + catch (Connection.ConnectionException e) + { + e.printStackTrace(); //TODO. + } + catch (Sender.SenderClosingException e) + { + e.printStackTrace(); //TODO. + } + catch (Sender.SenderCreationException e) + { + e.printStackTrace(); //TODO. + } + catch (AmqpErrorException e) + { + e.printStackTrace(); //TODO. + } + + } + + protected boolean hasSingleLinkPerConnectionMode() + { + return false; + } + + protected void printUsage(Options options) + { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp(USAGE_STRING, options ); + } + +} diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java new file mode 100644 index 0000000000..65d27b21f8 --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java @@ -0,0 +1,136 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.amqp_1_0.client; + +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.commons.cli.Options; + +public class Dump extends Util +{ + private static final String USAGE_STRING = "dump [options]
\n\nOptions:"; + + + protected Dump(String[] args) + { + super(args); + } + + public static void main(String[] args) + { + new Dump(args).run(); + } + + @Override + protected boolean hasLinkDurableOption() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected boolean hasLinkNameOption() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected boolean hasResponseQueueOption() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected boolean hasSizeOption() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected boolean hasBlockOption() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected boolean hasStdInOption() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected boolean hasTxnOption() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected boolean hasModeOption() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected boolean hasCountOption() + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected void printUsage(Options options) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected void run() + { + final String queue = getArgs()[0]; + + try + { + Connection conn = newConnection(); + + Session session = conn.createSession(); + + + Sender s = session.createSender(queue, 10); + + Message message = new Message("dump me"); + message.setDeliveryTag(new Binary("dump".getBytes())); + + s.send(message); + + s.close(); + session.close(); + conn.close(); + + } catch (Connection.ConnectionException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + catch (Sender.SenderCreationException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (Sender.SenderClosingException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } +} diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java new file mode 100644 index 0000000000..4d98655ad2 --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java @@ -0,0 +1,347 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.amqp_1_0.client; + +import org.apache.qpid.amqp_1_0.type.*; +import org.apache.qpid.amqp_1_0.type.messaging.*; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; + +import java.io.*; +import java.nio.ByteBuffer; +import java.util.*; + +public class Filereceiver extends Util +{ + private static final String USAGE_STRING = "filereceiver [options]
\n\nOptions:"; + + protected Filereceiver(String[] args) + { + super(args); + } + + @Override + protected boolean hasLinkDurableOption() + { + return true; + } + + @Override + protected boolean hasLinkNameOption() + { + return true; + } + + @Override + protected boolean hasResponseQueueOption() + { + return false; + } + + @Override + protected boolean hasSizeOption() + { + return false; + } + + @Override + protected boolean hasBlockOption() + { + return true; + } + + @Override + protected boolean hasStdInOption() + { + return false; + } + + @Override + protected boolean hasTxnOption() + { + return false; + } + + @Override + protected boolean hasModeOption() + { + return false; + } + + @Override + protected boolean hasCountOption() + { + return false; + } + + @Override + protected void printUsage(Options options) + { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp(USAGE_STRING, options ); + + } + + @Override + protected void run() + { + final String queue = getArgs()[0]; + final String directoryName = getArgs()[1]; + + try + { + Connection conn = newConnection(); + + Session session = conn.createSession(); + + final File directory = new File(directoryName); + if(directory.isDirectory() && directory.canWrite()) + { + File tmpDirectory = new File(directoryName, ".tmp"); + if(!tmpDirectory.exists()) + { + tmpDirectory.mkdir(); + } + + String[] unsettledFiles = tmpDirectory.list(); + + Map unsettled = new HashMap(); + final Map unsettledFileNames = new HashMap(); + + Accepted accepted = new Accepted(); + + for(String fileName : unsettledFiles) + { + File theFile = new File(tmpDirectory, fileName); + if(theFile.isFile()) + { + if(fileName.startsWith("~") && fileName.endsWith("~")) + { + theFile.delete(); + } + else + { + int splitPoint = fileName.indexOf("."); + String deliveryTagStr = fileName.substring(0,splitPoint); + String actualFileName = fileName.substring(splitPoint+1); + + byte[] bytes = new byte[deliveryTagStr.length()/2]; + + + for(int i = 0; i < bytes.length; i++) + { + char c = deliveryTagStr.charAt(2*i); + char d = deliveryTagStr.charAt(1+(2*i)); + + bytes[i] = (byte) (((c <= '9' ? c - '0' : c - 'W') << 4) + | (d <= '9' ? d - '0' : d - 'W')); + + } + Binary deliveryTag = new Binary(bytes); + unsettled.put(deliveryTag, accepted); + unsettledFileNames.put(deliveryTag, fileName); + } + } + + } + + Receiver r = session.createReceiver(queue, AcknowledgeMode.EO, getLinkName(), isDurableLink(), + unsettled); + + Map remoteUnsettled = r.getRemoteUnsettled(); + + for(Map.Entry entry : unsettledFileNames.entrySet()) + { + if(remoteUnsettled == null || !remoteUnsettled.containsKey(entry.getKey())) + { + + File tmpFile = new File(tmpDirectory, entry.getValue()); + final File dest = new File(directory, + entry.getValue().substring(entry.getValue().indexOf(".") + 1)); + if(dest.exists()) + { + System.err.println("Duplicate detected - filename " + dest.getName()); + } + + tmpFile.renameTo(dest); + } + } + + + int credit = 10; + + r.setCredit(UnsignedInteger.valueOf(credit), true); + + + int received = 0; + Message m = null; + do + { + m = isBlock() && received == 0 ? r.receive() : r.receive(10000); + if(m != null) + { + if(m.isResume() && unsettled.containsKey(m.getDeliveryTag())) + { + final String tmpFileName = unsettledFileNames.get(m.getDeliveryTag()); + final File unsettledFile = new File(tmpDirectory, + tmpFileName); + r.acknowledge(m, new Receiver.SettledAction() + { + public void onSettled(final Binary deliveryTag) + { + int splitPoint = tmpFileName.indexOf("."); + + String fileName = tmpFileName.substring(splitPoint+1); + + final File dest = new File(directory, fileName); + if(dest.exists()) + { + System.err.println("Duplicate detected - filename " + dest.getName()); + } + unsettledFile.renameTo(dest); + unsettledFileNames.remove(deliveryTag); + } + }); + } + else + { + received++; + List
sections = m.getPayload(); + Binary deliveryTag = m.getDeliveryTag(); + StringBuilder tagNameBuilder = new StringBuilder(); + + ByteBuffer dtbuf = deliveryTag.asByteBuffer(); + while(dtbuf.hasRemaining()) + { + tagNameBuilder.append(String.format("%02x", dtbuf.get())); + } + + + ApplicationProperties properties = null; + List data = new ArrayList(); + int totalSize = 0; + for(Section section : sections) + { + if(section instanceof ApplicationProperties) + { + properties = (ApplicationProperties) section; + } + else if(section instanceof AmqpValue) + { + AmqpValue value = (AmqpValue) section; + if(value.getValue() instanceof Binary) + { + Binary binary = (Binary) value.getValue(); + data.add(binary); + totalSize += binary.getLength(); + + } + else + { + // TODO exception + } + } + else if(section instanceof Data) + { + Data value = (Data) section; + Binary binary = value.getValue(); + data.add(binary); + totalSize += binary.getLength(); + + } + } + if(properties != null) + { + final String fileName = (String) properties.getValue().get("filename"); + byte[] fileData = new byte[totalSize]; + ByteBuffer buf = ByteBuffer.wrap(fileData); + int offset = 0; + for(Binary bin : data) + { + buf.put(bin.asByteBuffer()); + } + File outputFile = new File(tmpDirectory, "~"+fileName+"~"); + if(outputFile.exists()) + { + outputFile.delete(); + } + FileOutputStream fos = new FileOutputStream(outputFile); + fos.write(fileData); + fos.flush(); + fos.close(); + + final File unsettledFile = new File(tmpDirectory, tagNameBuilder.toString() + "." + + fileName); + outputFile.renameTo(unsettledFile); + r.acknowledge(m, new Receiver.SettledAction() + { + public void onSettled(final Binary deliveryTag) + { + final File dest = new File(directory, fileName); + if(dest.exists()) + { + System.err.println("Duplicate detected - filename " + dest.getName()); + } + unsettledFile.renameTo(dest); + + } + }); + + } + } + } + } + while(m != null); + + + r.close(); + } + else + { + System.err.println("No such directory: " + directoryName); + } + session.close(); + conn.close(); + } + catch (Connection.ConnectionException e) + { + e.printStackTrace(); + } + catch (FileNotFoundException e) + { + e.printStackTrace(); //TODO. + } + catch (IOException e) + { + e.printStackTrace(); //TODO. + } + catch (AmqpErrorException e) + { + e.printStackTrace(); //TODO. + } + + } + + public static void main(String[] args) + { + new Filereceiver(args).run(); + } +} diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java new file mode 100644 index 0000000000..46e6ba537f --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java @@ -0,0 +1,296 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.amqp_1_0.client; + +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.DeliveryState; +import org.apache.qpid.amqp_1_0.type.Outcome; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.messaging.*; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.*; + +public class Filesender extends Util +{ + private static final String USAGE_STRING = "filesender [options]
\n\nOptions:"; + + protected Filesender(String[] args) + { + super(args); + } + + @Override + protected boolean hasLinkDurableOption() + { + return true; + } + + @Override + protected boolean hasLinkNameOption() + { + return true; + } + + @Override + protected boolean hasResponseQueueOption() + { + return false; + } + + @Override + protected boolean hasSizeOption() + { + return false; + } + + @Override + protected boolean hasBlockOption() + { + return false; + } + + @Override + protected boolean hasStdInOption() + { + return false; + } + + @Override + protected boolean hasTxnOption() + { + return false; + } + + @Override + protected boolean hasModeOption() + { + return false; + } + + @Override + protected boolean hasCountOption() + { + return false; + } + + @Override + protected void printUsage(Options options) + { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp(USAGE_STRING, options ); + + } + + @Override + protected void run() + { + final String queue = getArgs()[0]; + final String directoryName = getArgs()[1]; + + try + { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + Connection conn = newConnection(); + + Session session = conn.createSession(); + + File directory = new File(directoryName); + if(directory.isDirectory() && directory.canWrite()) + { + + File tmpDirectory = new File(directoryName, ".tmp"); + if(!tmpDirectory.exists()) + { + tmpDirectory.mkdir(); + } + + String[] unsettledFiles = tmpDirectory.list(); + + + + Map unsettled = new HashMap(); + Map unsettledFileNames = new HashMap(); + for(String fileName : unsettledFiles) + { + File aFile = new File(tmpDirectory, fileName); + if(aFile.canRead() && aFile.canWrite()) + { + Binary deliveryTag = new Binary(md5.digest(fileName.getBytes())); + unsettled.put(deliveryTag, null); + unsettledFileNames.put(deliveryTag, fileName); + } + } + + + Sender s = session.createSender(queue, 10, AcknowledgeMode.EO, getLinkName(), isDurableLink(), + unsettled); + + Map remoteUnsettled = s.getRemoteUnsettled(); + + for(Map.Entry entry: unsettledFileNames.entrySet()) + { + if(remoteUnsettled == null || !remoteUnsettled.containsKey(entry.getKey())) + { + (new File(tmpDirectory, entry.getValue())).renameTo(new File(directory, entry.getValue())); + } + } + + if(remoteUnsettled != null) + { + for(Map.Entry entry : remoteUnsettled.entrySet()) + { + if(entry.getValue() instanceof Accepted) + { + final String fileName = unsettledFileNames.get(entry.getKey()); + if(fileName != null) + { + + Message resumed = new Message(); + resumed.setDeliveryTag(entry.getKey()); + resumed.setDeliveryState(entry.getValue()); + resumed.setResume(Boolean.TRUE); + resumed.setSettled(Boolean.TRUE); + + + + final File unsettledFile = new File(tmpDirectory, fileName); + unsettledFile.delete(); + + s.send(resumed); + + } + + } + else if(entry.getValue() instanceof Received || entry.getValue() == null) + { + final File unsettledFile = new File(tmpDirectory, unsettledFileNames.get(entry.getKey())); + Message resumed = createMessageFromFile(md5, unsettledFileNames.get(entry.getKey()), unsettledFile); + resumed.setResume(Boolean.TRUE); + Sender.OutcomeAction action = new Sender.OutcomeAction() + { + public void onOutcome(Binary deliveryTag, Outcome outcome) + { + if(outcome instanceof Accepted) + { + unsettledFile.delete(); + } + } + }; + s.send(resumed, action); + + } + } + } + + + + String[] files = directory.list(); + + for(String fileName : files) + { + final File file = new File(directory, fileName); + + if(file.canRead() && file.canWrite() && !file.isDirectory()) + { + Message message = createMessageFromFile(md5, fileName, file); + + final File unsettledFile = new File(tmpDirectory, fileName); + + Sender.OutcomeAction action = new Sender.OutcomeAction() + { + public void onOutcome(Binary deliveryTag, Outcome outcome) + { + if(outcome instanceof Accepted) + { + unsettledFile.delete(); + } + } + }; + + file.renameTo(unsettledFile); + + s.send(message, action); + } + } + + s.close(); + } + else + { + System.err.println("No such directory: " + directory); + } + session.close(); + conn.close(); + } + catch (Connection.ConnectionException e) + { + e.printStackTrace(); + } + catch (Sender.SenderCreationException e) + { + e.printStackTrace(); + } catch (FileNotFoundException e) + { + e.printStackTrace(); + } catch (IOException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (NoSuchAlgorithmException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } catch (Sender.SenderClosingException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + + } + + private Message createMessageFromFile(MessageDigest md5, String fileName, File file) throws IOException + { + FileInputStream fis = new FileInputStream(file); + byte[] data = new byte[(int) file.length()]; + + int read = fis.read(data); + + fis.close(); + + Section applicationProperties = new ApplicationProperties(Collections.singletonMap("filename", fileName)); + Section amqpValue = new Data(new Binary(data)); + Message message = new Message(Arrays.asList(applicationProperties, amqpValue)); + Binary deliveryTag = new Binary(md5.digest(fileName.getBytes())); + message.setDeliveryTag(deliveryTag); + md5.reset(); + return message; + } + + public static void main(String[] args) + { + new Filesender(args).run(); + } +} diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Receive.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Receive.java new file mode 100644 index 0000000000..0da9dc3fb7 --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Receive.java @@ -0,0 +1,246 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.amqp_1_0.client; + +import org.apache.qpid.amqp_1_0.type.AmqpErrorException; +import org.apache.qpid.amqp_1_0.type.Symbol; +import org.apache.qpid.amqp_1_0.type.UnsignedInteger; +import org.apache.qpid.amqp_1_0.type.UnsignedLong; +import org.apache.commons.cli.*; +import org.apache.qpid.amqp_1_0.type.messaging.ExactSubjectFilter; +import org.apache.qpid.amqp_1_0.type.messaging.Filter; +import org.apache.qpid.amqp_1_0.type.messaging.MatchingSubjectFilter; + +import java.util.Collections; + +public class Receive extends Util +{ + private static final String USAGE_STRING = "receive [options]
\n\nOptions:"; + private static final UnsignedLong UNSIGNED_LONG_ONE = UnsignedLong.valueOf(1L); + private UnsignedLong _lastCorrelationId; + + public static void main(String[] args) + { + new Receive(args).run(); + } + + + public Receive(final String[] args) + { + super(args); + } + + @Override + protected boolean hasLinkDurableOption() + { + return true; + } + + @Override + protected boolean hasLinkNameOption() + { + return true; + } + + @Override + protected boolean hasResponseQueueOption() + { + return false; + } + + @Override + protected boolean hasSizeOption() + { + return false; + } + + @Override + protected boolean hasBlockOption() + { + return true; + } + + @Override + protected boolean hasStdInOption() + { + return true; + } + + @Override + protected boolean hasTxnOption() + { + return true; + } + + @Override + protected boolean hasModeOption() + { + return true; + } + + @Override + protected boolean hasCountOption() + { + return true; + } + + @Override + protected boolean hasWindowSizeOption() + { + return true; + } + + @Override + protected boolean hasFilterOption() + { + return true; + } + + protected void run() + { + + try + { + final String queue = getArgs()[0]; + + String message = ""; + + Connection conn = newConnection(); + + + Session session = conn.createSession(); + + Filter filter = null; + if(getFilter() != null) + { + String[] filterParts = getFilter().split("=",2); + if("exact-subject".equals(filterParts[0])) + { + filter = new ExactSubjectFilter(filterParts[1]); + } + else if("matching-subject".equals(filterParts[0])) + { + filter = new MatchingSubjectFilter(filterParts[1]); + } + else + { + System.err.println("Unknown filter type: " + filterParts[0]); + } + } + + Receiver r = + filter == null + ? session.createReceiver(queue, getMode(), getLinkName(), isDurableLink()) + : session.createReceiver(queue, getMode(), getLinkName(), isDurableLink(), Collections.singletonMap(Symbol.valueOf("filter"), filter), null); + Transaction txn = null; + + int credit = 0; + int receivedCount = 0; + + if(!useStdIn()) + { + if(getArgs().length <= 2) + { + + Transaction txn2 = null; + if(useTran()) + { + txn = session.createSessionLocalTransaction(); + txn2 = session.createSessionLocalTransaction(); + } + + for(int i = 0; i < getCount(); i++) + { + + if(credit == 0) + { + if(getCount() - i <= getWindowSize()) + { + credit = getCount() - i; + + } + else + { + credit = getWindowSize(); + + } + + { + r.setCredit(UnsignedInteger.valueOf(credit), false); + } + if(!isBlock()) + r.drain(); + } + + Message m = isBlock() ? r.receive() : r.receive(1000L); + credit--; + if(m==null) + { + break; + } + + + + r.acknowledge(m.getDeliveryTag(),txn); + + receivedCount++; + + System.out.println("Received Message : " + m.getPayload()); + } + + if(useTran()) + { + txn.commit(); + } + } + else + { + // TODO + } + } + else + { + // TODO + } + r.close(); + session.close(); + conn.close(); + System.out.println("Total Messages Received: " + receivedCount); + } + catch (Connection.ConnectionException e) + { + e.printStackTrace(); //TODO. + } + catch (AmqpErrorException e) + { + e.printStackTrace(); //TODO. + } + + } + + protected void printUsage(Options options) + { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp(USAGE_STRING, options ); + } + +} diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Request.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Request.java new file mode 100644 index 0000000000..6e1d15376c --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Request.java @@ -0,0 +1,249 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.amqp_1_0.client; + +import org.apache.qpid.amqp_1_0.type.AmqpErrorException; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.UnsignedInteger; +import org.apache.qpid.amqp_1_0.type.UnsignedLong; +import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; +import org.apache.qpid.amqp_1_0.type.messaging.Header; +import org.apache.qpid.amqp_1_0.type.messaging.Properties; +import org.apache.commons.cli.*; + +import java.util.Arrays; + +public class Request extends Util +{ + private static final String USAGE_STRING = "request [options]
[ ...]\n\nOptions:"; + + public static void main(String[] args) + { + new Request(args).run(); + } + + public Request(String[] args) + { + super(args); + } + + @Override + protected boolean hasLinkDurableOption() + { + return false; + } + + @Override + protected boolean hasLinkNameOption() + { + return false; + } + + @Override + protected boolean hasResponseQueueOption() + { + return false; + } + + @Override + protected boolean hasSizeOption() + { + return true; + } + + @Override + protected boolean hasBlockOption() + { + return false; + } + + @Override + protected boolean hasStdInOption() + { + return false; + } + + @Override + protected boolean hasTxnOption() + { + return true; + } + + @Override + protected boolean hasModeOption() + { + return true; + } + + @Override + protected boolean hasCountOption() + { + return true; + } + + @Override + protected boolean hasWindowSizeOption() + { + return true; + } + + public void run() + { + + try + { + + + final String queue = getArgs()[0]; + + String message = ""; + + Connection conn = newConnection(); + Session session = conn.createSession(); + + Connection conn2; + Session session2; + Receiver responseReceiver; + + if(isUseMultipleConnections()) + { + conn2 = newConnection(); + session2 = conn2.createSession(); + responseReceiver = session2.createTemporaryQueueReceiver(); + } + else + { + conn2 = null; + session2 = null; + responseReceiver = session.createTemporaryQueueReceiver(); + } + + + + + responseReceiver.setCredit(UnsignedInteger.valueOf(getWindowSize()), true); + + + + Sender s = session.createSender(queue, getWindowSize(), getMode()); + + Transaction txn = null; + + if(useTran()) + { + txn = session.createSessionLocalTransaction(); + } + + int received = 0; + + if(getArgs().length >= 2) + { + message = getArgs()[1]; + if(message.length() < getMessageSize()) + { + StringBuilder builder = new StringBuilder(getMessageSize()); + builder.append(message); + for(int x = message.length(); x < getMessageSize(); x++) + { + builder.append('.'); + } + message = builder.toString(); + } + + for(int i = 0; i < getCount(); i++) + { + Properties properties = new Properties(); + properties.setMessageId(UnsignedLong.valueOf(i)); + properties.setReplyTo(responseReceiver.getAddress()); + + AmqpValue amqpValue = new AmqpValue(message); + Section[] sections = { new Header() , properties, amqpValue}; + final Message message1 = new Message(Arrays.asList(sections)); + + s.send(message1, txn); + + Message responseMessage = responseReceiver.receive(false); + if(responseMessage != null) + { + responseReceiver.acknowledge(responseMessage.getDeliveryTag(),txn); + received++; + } + } + } + + if(txn != null) + { + txn.commit(); + } + + + while(received < getCount()) + { + Message responseMessage = responseReceiver.receive(); + responseReceiver.acknowledge(responseMessage.getDeliveryTag()); + received++; + } + + + + + s.close(); + session.close(); + conn.close(); + + if(session2 != null) + { + session2.close(); + conn2.close(); + } + } + catch (Connection.ConnectionException e) + { + e.printStackTrace(); //TODO. + } + catch (Sender.SenderClosingException e) + { + e.printStackTrace(); //TODO. + } + catch (Sender.SenderCreationException e) + { + e.printStackTrace(); //TODO. + } + catch (AmqpErrorException e) + { + e.printStackTrace(); //TODO. + } + + } + + protected boolean hasSingleLinkPerConnectionMode() + { + return true; + } + + protected void printUsage(Options options) + { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp(USAGE_STRING, options ); + } + +} diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java new file mode 100644 index 0000000000..8d9de4893f --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java @@ -0,0 +1,347 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.amqp_1_0.client; + +import org.apache.qpid.amqp_1_0.type.AmqpErrorException; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.UnsignedInteger; +import org.apache.qpid.amqp_1_0.type.UnsignedLong; +import org.apache.qpid.amqp_1_0.type.messaging.Properties; +import org.apache.commons.cli.*; + +import java.util.*; + +public class Respond extends Util +{ + private static final String USAGE_STRING = "respond [options]
\n\nOptions:"; + private Connection _conn; + private Session _session; + private Receiver _receiver; + private Transaction _txn; + private Map _senders; + private UnsignedLong _responseMsgId = UnsignedLong.ZERO; + private Connection _conn2; + private Session _session2; + + public Respond(final String[] args) + { + super(args); + } + + @Override + protected boolean hasLinkDurableOption() + { + return false; + } + + @Override + protected boolean hasLinkNameOption() + { + return false; + } + + @Override + protected boolean hasResponseQueueOption() + { + return true; + } + + @Override + protected boolean hasSizeOption() + { + return false; + } + + @Override + protected boolean hasBlockOption() + { + return true; + } + + @Override + protected boolean hasStdInOption() + { + return false; + } + + @Override + protected boolean hasTxnOption() + { + return true; + } + + @Override + protected boolean hasModeOption() + { + return true; + } + + @Override + protected boolean hasCountOption() + { + return true; + } + + @Override + protected boolean hasSingleLinkPerConnectionMode() + { + return true; + } + + + @Override + protected boolean hasWindowSizeOption() + { + return true; + } + + public static void main(String[] args) + { + new Respond(args).run(); + } + + public void run() + { + try + { + + _senders = new HashMap(); + + final String queue = getArgs()[0]; + + String message = ""; + + _conn = newConnection(); + + + + if(isUseMultipleConnections()) + { + _conn2 = newConnection(); + _session2 = _conn2.createSession(); + } + + + _session = _conn.createSession(); + + + _receiver = _session.createReceiver(queue, getMode()); + _txn = null; + + int credit = 0; + int receivedCount = 0; + _responseMsgId = UnsignedLong.ZERO; + + Random random = null; + int batch = 0; + List txnMessages = null; + if(useTran()) + { + if(getRollbackRatio() != 0) + { + random = new Random(); + } + batch = getBatchSize(); + _txn = _session.createSessionLocalTransaction(); + txnMessages = new ArrayList(batch); + } + + + for(int i = 0; receivedCount < getCount(); i++) + { + + if(credit == 0) + { + if(getCount() - i <= getWindowSize()) + { + credit = getCount() - i; + + } + else + { + credit = getWindowSize(); + + } + + _receiver.setCredit(UnsignedInteger.valueOf(credit), false); + + if(!isBlock()) + _receiver.drain(); + } + + Message m = isBlock() ? (receivedCount == 0 ? _receiver.receive() : _receiver.receive(10000L)) : _receiver.receive(1000L); + credit--; + if(m==null) + { + if(useTran() && batch != getBatchSize()) + { + _txn.commit(); + } + break; + } + + System.out.println("Received Message: " + m.getPayload()); + + respond(m); + + + + if(useTran()) + { + + txnMessages.add(m); + + if(--batch == 0) + { + + if(getRollbackRatio() == 0 || random.nextDouble() >= getRollbackRatio()) + { + _txn.commit(); + txnMessages.clear(); + receivedCount += getBatchSize(); + } + else + { + System.out.println("Random Rollback"); + _txn.rollback(); + double result; + do + { + _txn = _session.createSessionLocalTransaction(); + + for(Message msg : txnMessages) + { + respond(msg); + } + + result = random.nextDouble(); + if(result sections = m.getPayload(); + String replyTo = null; + Object correlationId = null; + for(Section section : sections) + { + if(section instanceof Properties) + { + replyTo = getResponseQueue() == null ? ((Properties)section).getReplyTo() : getResponseQueue(); + correlationId = ((Properties) section).getMessageId(); + break; + } + } + + if(replyTo != null) + { + Sender s = _senders.get(replyTo); + if(s == null) + { + s = (isUseMultipleConnections() ? _session2 : _session).createSender(replyTo,getWindowSize()); + _senders.put(replyTo, s); + } + + List
replySections = new ArrayList
(sections); + + ListIterator
sectionIterator = replySections.listIterator(); + + while(sectionIterator.hasNext()) + { + Section section = sectionIterator.next(); + if(section instanceof Properties) + { + Properties newProps = new Properties(); + newProps.setTo(replyTo); + newProps.setCorrelationId(correlationId); + newProps.setMessageId(_responseMsgId); + _responseMsgId = _responseMsgId.add(UnsignedLong.ONE); + sectionIterator.set(newProps); + } + } + + Message replyMessage = new Message(replySections); + System.out.println("Sent Message: " + replySections); + s.send(replyMessage, _txn); + + } + _receiver.acknowledge(m.getDeliveryTag(), _txn); + } + + protected void printUsage(Options options) + { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp(USAGE_STRING, options ); + } + +} diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Send.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Send.java new file mode 100644 index 0000000000..6f6575e083 --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Send.java @@ -0,0 +1,244 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.amqp_1_0.client; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.util.Arrays; + +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.UnsignedLong; +import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; +import org.apache.qpid.amqp_1_0.type.messaging.Data; +import org.apache.qpid.amqp_1_0.type.messaging.Properties; +import org.apache.commons.cli.*; + +public class Send extends Util +{ + private static final String USAGE_STRING = "send [options]
[ ...]\n\nOptions:"; + private static final char[] HEX = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + + + public static void main(String[] args) throws Sender.SenderCreationException, Sender.SenderClosingException, Connection.ConnectionException + { + new Send(args).run(); + } + + + public Send(final String[] args) + { + super(args); + } + + @Override + protected boolean hasLinkDurableOption() + { + return true; + } + + @Override + protected boolean hasLinkNameOption() + { + return true; + } + + @Override + protected boolean hasResponseQueueOption() + { + return false; + } + + @Override + protected boolean hasSizeOption() + { + return true; + } + + @Override + protected boolean hasBlockOption() + { + return false; + } + + @Override + protected boolean hasStdInOption() + { + return true; + } + + @Override + protected boolean hasTxnOption() + { + return true; + } + + @Override + protected boolean hasModeOption() + { + return true; + } + + @Override + protected boolean hasCountOption() + { + return true; + } + + @Override + protected boolean hasWindowSizeOption() + { + return true; + } + + @Override + protected boolean hasSubjectOption() + { + return true; + } + + public void run() + { + + final String queue = getArgs()[0]; + + String message = ""; + + try + { + Connection conn = newConnection(); + + Session session = conn.createSession(); + + + Sender s = session.createSender(queue, getWindowSize(), getMode(), getLinkName()); + + Transaction txn = null; + + if(useTran()) + { + txn = session.createSessionLocalTransaction(); + } + + if(!useStdIn()) + { + if(getArgs().length <= 2) + { + if(getArgs().length == 2) + { + message = getArgs()[1]; + } + for(int i = 0; i < getCount(); i++) + { + + Properties properties = new Properties(); + properties.setMessageId(UnsignedLong.valueOf(i)); + if(getSubject() != null) + { + properties.setSubject(getSubject()); + } + Section bodySection; + byte[] bytes = (message + " " + i).getBytes(); + if(bytes.length < getMessageSize()) + { + byte[] origBytes = bytes; + bytes = new byte[getMessageSize()]; + System.arraycopy(origBytes,0,bytes,0,origBytes.length); + for(int x = origBytes.length; x < bytes.length; x++) + { + bytes[x] = (byte) '.'; + } + bodySection = new Data(new Binary(bytes)); + } + else + { + bodySection = new AmqpValue(message + " " + i); + } + + Section[] sections = {properties, bodySection}; + final Message message1 = new Message(Arrays.asList(sections)); + + s.send(message1, txn); + } + } + else + { + for(int i = 1; i < getArgs().length; i++) + { + s.send(new Message(getArgs()[i]), txn); + } + + } + } + else + { + LineNumberReader buf = new LineNumberReader(new InputStreamReader(System.in)); + + + try + { + while((message = buf.readLine()) != null) + { + s.send(new Message(message), txn); + } + } + catch (IOException e) + { + // TODO + e.printStackTrace(); + } + } + + if(txn != null) + { + txn.commit(); + } + + s.close(); + + session.close(); + conn.close(); + } + catch (Sender.SenderClosingException e) + { + e.printStackTrace(); //TODO. + } + catch (Connection.ConnectionException e) + { + e.printStackTrace(); //TODO. + } + catch (Sender.SenderCreationException e) + { + e.printStackTrace(); //TODO. + } + + + } + + protected void printUsage(Options options) + { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp(USAGE_STRING, options ); + } + +} diff --git a/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Util.java b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Util.java new file mode 100644 index 0000000000..6fe2a6d510 --- /dev/null +++ b/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Util.java @@ -0,0 +1,529 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.amqp_1_0.client; + +import org.apache.qpid.amqp_1_0.transport.Container; +import org.apache.commons.cli.*; + +import java.util.logging.*; + +public abstract class Util +{ + + private static final Logger FRAME_LOGGER = Logger.getLogger("FRM"); + private static final Logger RAW_LOGGER = Logger.getLogger("RAW"); + private String _host; + private String _username; + private String _password; + private int _port; + private int _count; + private boolean _useStdIn; + private boolean _useTran; + private String[] _args; + private AcknowledgeMode _mode; + private boolean _block; + private int _frameSize; + private int _messageSize; + private String _responseQueue; + private int _batchSize; + private double _rollbackRatio; + private String _linkName; + private String _containerName; + private boolean _durableLink; + private boolean _useMultipleConnections; + private int _windowSize = 100; + private String _subject; + private String _filter; + private String _remoteHost; + private boolean _useSSL; + + protected Util(String[] args) + { + CommandLineParser cmdLineParse = new PosixParser(); + + Options options = new Options(); + options.addOption("h","help",false,"show this help message and exit"); + options.addOption(OptionBuilder.withLongOpt("host") + .withDescription( "host to connect to (default 0.0.0.0)" ) + .hasArg(true) + .withArgName("HOST") + .create('H')); + options.addOption(OptionBuilder.withLongOpt("username") + .withDescription( "username to use for authentication" ) + .hasArg(true) + .withArgName("USERNAME") + .create('u')); + options.addOption(OptionBuilder.withLongOpt("password") + .withDescription( "password to use for authentication" ) + .hasArg(true) + .withArgName("PASSWORD") + .create('w')); + options.addOption(OptionBuilder.withLongOpt("port") + .withDescription( "port to connect to (default 5672)" ) + .hasArg(true) + .withArgName("PORT") + .create('p')); + options.addOption(OptionBuilder.withLongOpt("frame-size") + .withDescription( "specify the maximum frame size" ) + .hasArg(true) + .withArgName("FRAME_SIZE") + .create('f')); + options.addOption(OptionBuilder.withLongOpt("container-name") + .withDescription( "Container name" ) + .hasArg(true) + .withArgName("CONTAINER_NAME") + .create('C')); + + options.addOption(OptionBuilder.withLongOpt("ssl") + .withDescription("Use SSL") + .create('S')); + + options.addOption(OptionBuilder.withLongOpt("remote-hostname") + .withDescription( "hostname to supply in the open frame" ) + .hasArg(true) + .withArgName("HOST") + .create('O')); + + if(hasBlockOption()) + options.addOption(OptionBuilder.withLongOpt("block") + .withDescription("block until messages arrive") + .create('b')); + + if(hasCountOption()) + options.addOption(OptionBuilder.withLongOpt("count") + .withDescription( "number of messages to send (default 1)" ) + .hasArg(true) + .withArgName("COUNT") + .create('c')); + if(hasModeOption()) + options.addOption(OptionBuilder.withLongOpt("acknowledge-mode") + .withDescription( "acknowledgement mode: AMO|ALO|EO (At Least Once, At Most Once, Exactly Once" ) + .hasArg(true) + .withArgName("MODE") + .create('k')); + + if(hasSubjectOption()) + options.addOption(OptionBuilder.withLongOpt("subject") + .withDescription( "subject message property" ) + .hasArg(true) + .withArgName("SUBJECT") + .create('s')); + + + if(hasSingleLinkPerConnectionMode()) + options.addOption(OptionBuilder.withLongOpt("single-link-per-connection") + .withDescription("acknowledgement mode: AMO|ALO|EO (At Least Once, At Most Once, Exactly Once") + .hasArg(false) + .create('Z')); + + if(hasFilterOption()) + options.addOption(OptionBuilder.withLongOpt("filter") + .withDescription("filter, e.g. exact-subject=hello; matching-subject=%.a.#") + .hasArg(true) + .withArgName("=") + .create('F')); + + + if(hasTxnOption()) + { + options.addOption("x","txn",false,"use transactions"); + options.addOption(OptionBuilder.withLongOpt("batch-size") + .withDescription( "transaction batch size (default: 1)" ) + .hasArg(true) + .withArgName("BATCH-SIZE") + .create('B')); + options.addOption(OptionBuilder.withLongOpt("rollback-ratio") + .withDescription( "rollback ratio - must be between 0 and 1 (default: 0)" ) + .hasArg(true) + .withArgName("RATIO") + .create('R')); + } + + if(hasLinkDurableOption()) + { + options.addOption("d","durable-link",false,"use a durable link"); + } + + if(hasStdInOption()) + options.addOption("i","stdin",false,"read messages from stdin (one message per line)"); + + options.addOption(OptionBuilder.withLongOpt("trace") + .withDescription("trace logging specified categories: RAW, FRM") + .hasArg(true) + .withArgName("TRACE") + .create('t')); + if(hasSizeOption()) + options.addOption(OptionBuilder.withLongOpt("message-size") + .withDescription( "size to pad outgoing messages to" ) + .hasArg(true) + .withArgName("SIZE") + .create('z')); + + if(hasResponseQueueOption()) + options.addOption(OptionBuilder.withLongOpt("response-queue") + .withDescription( "response queue to reply to" ) + .hasArg(true) + .withArgName("RESPONSE_QUEUE") + .create('r')); + + if(hasLinkNameOption()) + { + options.addOption(OptionBuilder.withLongOpt("link") + .withDescription( "link name" ) + .hasArg(true) + .withArgName("LINK") + .create('l')); + } + + if(hasWindowSizeOption()) + { + options.addOption(OptionBuilder.withLongOpt("window-size") + .withDescription("credit window size") + .hasArg(true) + .withArgName("WINDOW-SIZE") + .create('W')); + } + + CommandLine cmdLine = null; + try + { + cmdLine = cmdLineParse.parse(options, args); + + } + catch (ParseException e) + { + printUsage(options); + System.exit(-1); + } + + if(cmdLine.hasOption('h') || cmdLine.getArgList().isEmpty()) + { + printUsage(options); + System.exit(0); + } + _host = cmdLine.getOptionValue('H',"0.0.0.0"); + _remoteHost = cmdLine.getOptionValue('O',null); + String portStr = cmdLine.getOptionValue('p',"5672"); + String countStr = cmdLine.getOptionValue('c',"1"); + + _useSSL = cmdLine.hasOption('S'); + + if(hasWindowSizeOption()) + { + String windowSizeStr = cmdLine.getOptionValue('W',"100"); + _windowSize = Integer.parseInt(windowSizeStr); + } + + if(hasSubjectOption()) + { + _subject = cmdLine.getOptionValue('s'); + } + + if(cmdLine.hasOption('u')) + { + _username = cmdLine.getOptionValue('u'); + } + + if(cmdLine.hasOption('w')) + { + _password = cmdLine.getOptionValue('w'); + } + + if(cmdLine.hasOption('F')) + { + _filter = cmdLine.getOptionValue('F'); + } + + _port = Integer.parseInt(portStr); + + _containerName = cmdLine.getOptionValue('C'); + + if(hasBlockOption()) + _block = cmdLine.hasOption('b'); + + if(hasLinkNameOption()) + _linkName = cmdLine.getOptionValue('l'); + + + if(hasLinkDurableOption()) + _durableLink = cmdLine.hasOption('d'); + + if(hasCountOption()) + _count = Integer.parseInt(countStr); + + if(hasStdInOption()) + _useStdIn = cmdLine.hasOption('i'); + + if(hasSingleLinkPerConnectionMode()) + _useMultipleConnections = cmdLine.hasOption('Z'); + + if(hasTxnOption()) + { + _useTran = cmdLine.hasOption('x'); + _batchSize = Integer.parseInt(cmdLine.getOptionValue('B',"1")); + _rollbackRatio = Double.parseDouble(cmdLine.getOptionValue('R',"0")); + } + + if(hasModeOption()) + { + _mode = AcknowledgeMode.ALO; + + if(cmdLine.hasOption('k')) + { + _mode = AcknowledgeMode.valueOf(cmdLine.getOptionValue('k')); + } + } + + if(hasResponseQueueOption()) + { + _responseQueue = cmdLine.getOptionValue('r'); + } + + _frameSize = Integer.parseInt(cmdLine.getOptionValue('f',"65536")); + + if(hasSizeOption()) + { + _messageSize = Integer.parseInt(cmdLine.getOptionValue('z',"-1")); + } + + String categoriesList = cmdLine.getOptionValue('t'); + String[]categories = categoriesList == null ? new String[0] : categoriesList.split("[, ]"); + for(String cat : categories) + { + if(cat.equalsIgnoreCase("FRM")) + { + FRAME_LOGGER.setLevel(Level.FINE); + Formatter formatter = new Formatter() + { + @Override + public String format(final LogRecord record) + { + return "[" + record.getMillis() + " FRM]\t" + record.getMessage() + "\n"; + } + }; + for(Handler handler : FRAME_LOGGER.getHandlers()) + { + FRAME_LOGGER.removeHandler(handler); + } + Handler handler = new ConsoleHandler(); + handler.setLevel(Level.FINE); + handler.setFormatter(formatter); + FRAME_LOGGER.addHandler(handler); + } + else if (cat.equalsIgnoreCase("RAW")) + { + RAW_LOGGER.setLevel(Level.FINE); + Formatter formatter = new Formatter() + { + @Override + public String format(final LogRecord record) + { + return "[" + record.getMillis() + " RAW]\t" + record.getMessage() + "\n"; + } + }; + for(Handler handler : RAW_LOGGER.getHandlers()) + { + RAW_LOGGER.removeHandler(handler); + } + Handler handler = new ConsoleHandler(); + handler.setLevel(Level.FINE); + handler.setFormatter(formatter); + RAW_LOGGER.addHandler(handler); + } + } + + + _args = cmdLine.getArgs(); + + } + + protected boolean hasFilterOption() + { + return false; + } + + protected boolean hasSubjectOption() + { + return false; + } + + protected boolean hasWindowSizeOption() + { + return false; + } + + protected boolean hasSingleLinkPerConnectionMode() + { + return false; + } + + protected abstract boolean hasLinkDurableOption(); + + protected abstract boolean hasLinkNameOption(); + + protected abstract boolean hasResponseQueueOption(); + + protected abstract boolean hasSizeOption(); + + protected abstract boolean hasBlockOption(); + + protected abstract boolean hasStdInOption(); + + protected abstract boolean hasTxnOption(); + + protected abstract boolean hasModeOption(); + + protected abstract boolean hasCountOption(); + + public String getHost() + { + return _host; + } + + public String getUsername() + { + return _username; + } + + public String getPassword() + { + return _password; + } + + public int getPort() + { + return _port; + } + + public int getCount() + { + return _count; + } + + public boolean useStdIn() + { + return _useStdIn; + } + + public boolean useTran() + { + return _useTran; + } + + public AcknowledgeMode getMode() + { + return _mode; + } + + public boolean isBlock() + { + return _block; + } + + public String[] getArgs() + { + return _args; + } + + public int getMessageSize() + { + return _messageSize; + } + + public String getResponseQueue() + { + return _responseQueue; + } + + public int getBatchSize() + { + return _batchSize; + } + + public double getRollbackRatio() + { + return _rollbackRatio; + } + + public String getLinkName() + { + return _linkName; + } + + public boolean isDurableLink() + { + return _durableLink; + } + + public boolean isUseMultipleConnections() + { + return _useMultipleConnections; + } + + public void setUseMultipleConnections(boolean useMultipleConnections) + { + _useMultipleConnections = useMultipleConnections; + } + + public String getSubject() + { + return _subject; + } + + public void setSubject(String subject) + { + _subject = subject; + } + + protected abstract void printUsage(final Options options); + + protected abstract void run(); + + + public Connection newConnection() throws Connection.ConnectionException + { + Container container = getContainerName() == null ? new Container() : new Container(getContainerName()); + return getUsername() == null ? new Connection(getHost(), getPort(), null, null, _frameSize, container, + _remoteHost == null ? getHost() : _remoteHost, _useSSL) + : new Connection(getHost(), getPort(), getUsername(), getPassword(), _frameSize, + container, _remoteHost == null ? getHost() : _remoteHost, _useSSL); + } + + public String getContainerName() + { + return _containerName; + } + + public int getWindowSize() + { + return _windowSize; + } + + public void setWindowSize(int windowSize) + { + _windowSize = windowSize; + } + + public String getFilter() + { + return _filter; + } +} diff --git a/java/amqp-1-0-client/resources/LICENSE b/java/amqp-1-0-client/resources/LICENSE new file mode 100644 index 0000000000..de4b130f35 --- /dev/null +++ b/java/amqp-1-0-client/resources/LICENSE @@ -0,0 +1,204 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + diff --git a/java/amqp-1-0-client/resources/NOTICE b/java/amqp-1-0-client/resources/NOTICE new file mode 100644 index 0000000000..8d1c3f3122 --- /dev/null +++ b/java/amqp-1-0-client/resources/NOTICE @@ -0,0 +1,5 @@ +Apache Qpid +Copyright 2006-2012 Apache Software Foundation +This product includes software developed at +Apache Software Foundation (http://www.apache.org/) + diff --git a/java/amqp-1-0-client/resources/README.txt b/java/amqp-1-0-client/resources/README.txt new file mode 100644 index 0000000000..35d25050fe --- /dev/null +++ b/java/amqp-1-0-client/resources/README.txt @@ -0,0 +1,7 @@ + +Documentation +-------------- +All of our user documentation can be accessed at: + +http://qpid.apache.org/documentation.html + diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Command.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Command.java deleted file mode 100644 index 3bb26744c4..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Command.java +++ /dev/null @@ -1,43 +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.amqp_1_0.client; - -import java.lang.reflect.InvocationTargetException; - -public class Command -{ - public static void main(String[] args) throws - ClassNotFoundException, - NoSuchMethodException, - InvocationTargetException, - IllegalAccessException, - InstantiationException - { - String name = args[0]; - String[] cmdArgs = new String[args.length-1]; - System.arraycopy(args,1,cmdArgs,0,args.length-1); - name = "org.apache.qpid.amqp_1_0.client." + String.valueOf(name.charAt(0)).toUpperCase() + name.substring(1).toLowerCase(); - Class clazz = (Class) Class.forName(name); - Util util = clazz.getDeclaredConstructor(String[].class).newInstance((Object)cmdArgs); - util.run(); - - } -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Connection.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Connection.java index e3d56fae09..e501662dbb 100644 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Connection.java +++ b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Connection.java @@ -20,6 +20,15 @@ */ package org.apache.qpid.amqp_1_0.client; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.net.ssl.SSLSocketFactory; import org.apache.qpid.amqp_1_0.framing.ConnectionHandler; import org.apache.qpid.amqp_1_0.transport.AMQPTransport; import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; @@ -30,17 +39,6 @@ import org.apache.qpid.amqp_1_0.type.FrameBody; import org.apache.qpid.amqp_1_0.type.SaslFrameBody; import org.apache.qpid.amqp_1_0.type.UnsignedInteger; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.nio.ByteBuffer; -import java.security.Principal; -import java.util.logging.Level; -import java.util.logging.Logger; - public class Connection { private static final Logger RAW_LOGGER = Logger.getLogger("RAW"); @@ -224,7 +222,6 @@ public class Connection } - //ConnectionHandler.OutputHandler outputHandler = new ConnectionHandler.OutputHandler(outputStream, out, _conn.getDescribedTypeRegistry()); ConnectionHandler.BytesOutputHandler outputHandler = new ConnectionHandler.BytesOutputHandler(outputStream, src, _conn); Thread outputThread = new Thread(outputHandler); outputThread.setDaemon(true); @@ -236,8 +233,6 @@ public class Connection final ConnectionHandler handler = new ConnectionHandler(_conn); final InputStream inputStream = s.getInputStream(); - //final AMQPTransport transport = new AMQPTransport(new AMQPFrameTransport(_conn)); - Thread inputThread = new Thread(new Runnable() { @@ -246,7 +241,6 @@ public class Connection try { doRead(handler, inputStream); -// doRead(transport, inputStream); } finally { @@ -268,85 +262,6 @@ public class Connection inputThread.setDaemon(true); inputThread.start(); -/* - Thread outputThread = new Thread(new Runnable() - { - - private int _lastWrite; - - public void run() - { - try - { -// doRead(handler, inputStream); - final Object lock = new Object(); - transport.setOutputStateChangeListener(new StateChangeListener() - { - - public void onStateChange(final boolean active) - { - synchronized (lock) - { - lock.notifyAll(); - } - } - }); - - synchronized(lock) - { - while(transport.isOpenForOutput()) - { - _lastWrite = 0; - transport.getNextBytes(new BytesProcessor() - { - - public void processBytes(final ByteBuffer buf) - { - _lastWrite = buf.remaining(); - try - { - outputStream.write(buf.array(), - buf.arrayOffset() + buf.position(), - buf.limit() - buf.position()); - } - catch (IOException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - }); - if(_lastWrite == 0 && transport.isOpenForOutput()) - { - try - { - lock.wait(1000); - } - catch (InterruptedException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - } - } - finally - { - if(_conn.closedForInput() && _conn.closedForOutput()) - { - try - { - s.close(); - } - catch (IOException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - } - }); -*/ - _conn.open(); } @@ -394,7 +309,7 @@ public class Connection } catch (IOException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } } @@ -419,7 +334,7 @@ public class Connection { int read; boolean done = false; - while(!done && (read = inputStream.read(buf)) != -1) + while(!handler.isDone() && (read = inputStream.read(buf)) != -1) { ByteBuffer bbuf = ByteBuffer.wrap(buf, 0, read); Binary b = new Binary(buf,0,read); @@ -428,12 +343,6 @@ public class Connection { RAW_LOGGER.fine("RECV [" + _conn.getRemoteAddress() + "] : " + b.toString()); } - /*System.err.println(b); - System.err.println("XXX: " + bbuf.hasRemaining() + "; " + handler.isDone()); - if(handler.isDone()) - { - System.err.println(handler.getClass().getName() + "IS DONE!"); - } */ while(bbuf.hasRemaining() && !handler.isDone()) { handler.parse(bbuf); @@ -444,7 +353,7 @@ public class Connection } catch (IOException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + e.printStackTrace(); } } diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Demo.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Demo.java deleted file mode 100644 index b58ce6bfe5..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Demo.java +++ /dev/null @@ -1,407 +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.amqp_1_0.client; - -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Options; -import org.apache.qpid.amqp_1_0.type.AmqpErrorException; -import org.apache.qpid.amqp_1_0.type.Section; -import org.apache.qpid.amqp_1_0.type.UnsignedInteger; -import org.apache.qpid.amqp_1_0.type.UnsignedLong; -import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; -import org.apache.qpid.amqp_1_0.type.messaging.ApplicationProperties; -import org.apache.qpid.amqp_1_0.type.messaging.Header; -import org.apache.qpid.amqp_1_0.type.messaging.Properties; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class Demo extends Util -{ - private static final String USAGE_STRING = "demo [options] [ ...]\n\nOptions:"; - private static final String OPCODE = "opcode"; - private static final String ACTION = "action"; - private static final String MESSAGE_ID = "message-id"; - private static final String VENDOR = "vendor"; - private static final String LOG = "log"; - private static final String RECEIVED = "received"; - private static final String TEST = "test"; - private static final String APACHE = "apache"; - private static final String SENT = "sent"; - private static final String LINK_REF = "link-ref"; - private static final String HOST = "host"; - private static final String PORT = "port"; - private static final String SASL_USER = "sasl-user"; - private static final String SASL_PASSWORD = "sasl-password"; - private static final String ROLE = "role"; - private static final String ADDRESS = "address"; - private static final String SENDER = "sender"; - private static final String SEND_MESSAGE = "send-message"; - private static final String ANNOUNCE = "announce"; - private static final String MESSAGE_VENDOR = "message-vendor"; - private static final String CREATE_LINK = "create-link"; - - public static void main(String[] args) - { - new Demo(args).run(); - } - - public Demo(String[] args) - { - super(args); - } - - @Override - protected boolean hasLinkDurableOption() - { - return false; - } - - @Override - protected boolean hasLinkNameOption() - { - return false; - } - - @Override - protected boolean hasResponseQueueOption() - { - return false; - } - - @Override - protected boolean hasSizeOption() - { - return false; - } - - @Override - protected boolean hasBlockOption() - { - return false; - } - - @Override - protected boolean hasStdInOption() - { - return false; - } - - @Override - protected boolean hasTxnOption() - { - return false; - } - - @Override - protected boolean hasModeOption() - { - return true; - } - - @Override - protected boolean hasCountOption() - { - return false; - } - - @Override - protected boolean hasWindowSizeOption() - { - return false; - } - - public void run() - { - - try - { - - final String vendor = getArgs()[0]; - final String queue = "control"; - - String message = ""; - - Connection conn = newConnection(); - Session session = conn.createSession(); - - - Receiver responseReceiver; - - responseReceiver = session.createTemporaryQueueReceiver(); - - - - - responseReceiver.setCredit(UnsignedInteger.valueOf(getWindowSize()), true); - - - - Sender s = session.createSender(queue, getWindowSize(), getMode()); - - - Properties properties = new Properties(); - properties.setMessageId(java.util.UUID.randomUUID()); - properties.setReplyTo(responseReceiver.getAddress()); - - HashMap appPropMap = new HashMap(); - ApplicationProperties appProperties = new ApplicationProperties(appPropMap); - - appPropMap.put(OPCODE, ANNOUNCE); - appPropMap.put(VENDOR, vendor); - appPropMap.put(ADDRESS,responseReceiver.getAddress()); - - AmqpValue amqpValue = new AmqpValue(message); - Section[] sections = { properties, appProperties, amqpValue}; - final Message message1 = new Message(Arrays.asList(sections)); - - s.send(message1); - - Map sendingLinks = new HashMap(); - Map receivingLinks = new HashMap(); - - - boolean done = false; - - while(!done) - { - boolean wait = true; - Message m = responseReceiver.receive(false); - if(m != null) - { - List
payload = m.getPayload(); - wait = false; - ApplicationProperties props = m.getApplicationProperties(); - Map map = props.getValue(); - String op = (String) map.get(OPCODE); - if("reset".equals(op)) - { - for(Sender sender : sendingLinks.values()) - { - try - { - sender.close(); - Session session1 = sender.getSession(); - session1.close(); - session1.getConnection().close(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - for(Receiver receiver : receivingLinks.values()) - { - try - { - receiver.close(); - receiver.getSession().close(); - receiver.getSession().getConnection().close(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - sendingLinks.clear(); - receivingLinks.clear(); - } - else if(CREATE_LINK.equals(op)) - { - Object linkRef = map.get(LINK_REF); - String host = (String) map.get(HOST); - Object o = map.get(PORT); - int port = Integer.parseInt(String.valueOf(o)); - String user = (String) map.get(SASL_USER); - String password = (String) map.get(SASL_PASSWORD); - String role = (String) map.get(ROLE); - String address = (String) map.get(ADDRESS); - System.err.println("Host: " + host + "\tPort: " + port + "\t user: " + user +"\t password: " + password); - try{ - - - Connection conn2 = new Connection(host, port, user, password, host); - Session session2 = conn2.createSession(); - if(sendingLinks.containsKey(linkRef)) - { - try - { - sendingLinks.remove(linkRef).close(); - } - catch (Exception e) - { - - } - } - if(receivingLinks.containsKey(linkRef)) - { - try - { - receivingLinks.remove(linkRef).close(); - } - catch (Exception e) - { - - } - } - if(SENDER.equals(role)) - { - - System.err.println("%%% Creating sender (" + linkRef + ")"); - Sender sender = session2.createSender(address); - sendingLinks.put(linkRef, sender); - } - else - { - - System.err.println("%%% Creating receiver (" + linkRef + ")"); - Receiver receiver2 = session2.createReceiver(address); - receiver2.setCredit(UnsignedInteger.valueOf(getWindowSize()), true); - - receivingLinks.put(linkRef, receiver2); - } - } - catch(Exception e) - { - e.printStackTrace(); - } - } - else if(SEND_MESSAGE.equals(op)) - { - Sender sender = sendingLinks.get(map.get(LINK_REF)); - Properties m2props = new Properties(); - Object messageId = map.get(MESSAGE_ID); - m2props.setMessageId(messageId); - Map m2propmap = new HashMap(); - m2propmap.put(OPCODE, TEST); - m2propmap.put(VENDOR, vendor); - ApplicationProperties m2appProps = new ApplicationProperties(m2propmap); - Message m2 = new Message(Arrays.asList(m2props, m2appProps, new AmqpValue("AMQP-"+messageId))); - sender.send(m2); - - Map m3propmap = new HashMap(); - m3propmap.put(OPCODE, LOG); - m3propmap.put(ACTION, SENT); - m3propmap.put(MESSAGE_ID, messageId); - m3propmap.put(VENDOR, vendor); - m3propmap.put(MESSAGE_VENDOR, vendor); - - - Message m3 = new Message(Arrays.asList(new ApplicationProperties(m3propmap), - new AmqpValue("AMQP-"+messageId))); - s.send(m3); - - } - - responseReceiver.acknowledge(m); - } - else - { - for(Map.Entry entry : receivingLinks.entrySet()) - { - m = entry.getValue().receive(false); - if(m != null) - { - wait = false; - - System.err.println("%%% Received message from " + entry.getKey()); - - Properties mp = m.getProperties(); - ApplicationProperties ap = m.getApplicationProperties(); - - Map m3propmap = new HashMap(); - m3propmap.put(OPCODE, LOG); - m3propmap.put(ACTION, RECEIVED); - m3propmap.put(MESSAGE_ID, mp.getMessageId()); - m3propmap.put(VENDOR, vendor); - m3propmap.put(MESSAGE_VENDOR, ap.getValue().get(VENDOR)); - - Message m3 = new Message(Arrays.asList(new ApplicationProperties(m3propmap), - new AmqpValue("AMQP-"+mp.getMessageId()))); - s.send(m3); - - entry.getValue().acknowledge(m); - } - - } - } - - if(wait) - { - try - { - Thread.sleep(500l); - } - catch (InterruptedException e) - { - e.printStackTrace(); //TODO. - } - } - - } - - - - - - - - - - s.close(); - session.close(); - conn.close(); - - } - catch (Connection.ConnectionException e) - { - e.printStackTrace(); //TODO. - } - catch (Sender.SenderClosingException e) - { - e.printStackTrace(); //TODO. - } - catch (Sender.SenderCreationException e) - { - e.printStackTrace(); //TODO. - } - catch (AmqpErrorException e) - { - e.printStackTrace(); //TODO. - } - - } - - protected boolean hasSingleLinkPerConnectionMode() - { - return false; - } - - protected void printUsage(Options options) - { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(USAGE_STRING, options ); - } - -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java deleted file mode 100644 index 65d27b21f8..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Dump.java +++ /dev/null @@ -1,136 +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.amqp_1_0.client; - -import org.apache.qpid.amqp_1_0.type.Binary; -import org.apache.commons.cli.Options; - -public class Dump extends Util -{ - private static final String USAGE_STRING = "dump [options]
\n\nOptions:"; - - - protected Dump(String[] args) - { - super(args); - } - - public static void main(String[] args) - { - new Dump(args).run(); - } - - @Override - protected boolean hasLinkDurableOption() - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected boolean hasLinkNameOption() - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected boolean hasResponseQueueOption() - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected boolean hasSizeOption() - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected boolean hasBlockOption() - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected boolean hasStdInOption() - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected boolean hasTxnOption() - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected boolean hasModeOption() - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected boolean hasCountOption() - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected void printUsage(Options options) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - protected void run() - { - final String queue = getArgs()[0]; - - try - { - Connection conn = newConnection(); - - Session session = conn.createSession(); - - - Sender s = session.createSender(queue, 10); - - Message message = new Message("dump me"); - message.setDeliveryTag(new Binary("dump".getBytes())); - - s.send(message); - - s.close(); - session.close(); - conn.close(); - - } catch (Connection.ConnectionException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - catch (Sender.SenderCreationException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } catch (Sender.SenderClosingException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java deleted file mode 100644 index 4d98655ad2..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filereceiver.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.amqp_1_0.client; - -import org.apache.qpid.amqp_1_0.type.*; -import org.apache.qpid.amqp_1_0.type.messaging.*; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Options; - -import java.io.*; -import java.nio.ByteBuffer; -import java.util.*; - -public class Filereceiver extends Util -{ - private static final String USAGE_STRING = "filereceiver [options]
\n\nOptions:"; - - protected Filereceiver(String[] args) - { - super(args); - } - - @Override - protected boolean hasLinkDurableOption() - { - return true; - } - - @Override - protected boolean hasLinkNameOption() - { - return true; - } - - @Override - protected boolean hasResponseQueueOption() - { - return false; - } - - @Override - protected boolean hasSizeOption() - { - return false; - } - - @Override - protected boolean hasBlockOption() - { - return true; - } - - @Override - protected boolean hasStdInOption() - { - return false; - } - - @Override - protected boolean hasTxnOption() - { - return false; - } - - @Override - protected boolean hasModeOption() - { - return false; - } - - @Override - protected boolean hasCountOption() - { - return false; - } - - @Override - protected void printUsage(Options options) - { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(USAGE_STRING, options ); - - } - - @Override - protected void run() - { - final String queue = getArgs()[0]; - final String directoryName = getArgs()[1]; - - try - { - Connection conn = newConnection(); - - Session session = conn.createSession(); - - final File directory = new File(directoryName); - if(directory.isDirectory() && directory.canWrite()) - { - File tmpDirectory = new File(directoryName, ".tmp"); - if(!tmpDirectory.exists()) - { - tmpDirectory.mkdir(); - } - - String[] unsettledFiles = tmpDirectory.list(); - - Map unsettled = new HashMap(); - final Map unsettledFileNames = new HashMap(); - - Accepted accepted = new Accepted(); - - for(String fileName : unsettledFiles) - { - File theFile = new File(tmpDirectory, fileName); - if(theFile.isFile()) - { - if(fileName.startsWith("~") && fileName.endsWith("~")) - { - theFile.delete(); - } - else - { - int splitPoint = fileName.indexOf("."); - String deliveryTagStr = fileName.substring(0,splitPoint); - String actualFileName = fileName.substring(splitPoint+1); - - byte[] bytes = new byte[deliveryTagStr.length()/2]; - - - for(int i = 0; i < bytes.length; i++) - { - char c = deliveryTagStr.charAt(2*i); - char d = deliveryTagStr.charAt(1+(2*i)); - - bytes[i] = (byte) (((c <= '9' ? c - '0' : c - 'W') << 4) - | (d <= '9' ? d - '0' : d - 'W')); - - } - Binary deliveryTag = new Binary(bytes); - unsettled.put(deliveryTag, accepted); - unsettledFileNames.put(deliveryTag, fileName); - } - } - - } - - Receiver r = session.createReceiver(queue, AcknowledgeMode.EO, getLinkName(), isDurableLink(), - unsettled); - - Map remoteUnsettled = r.getRemoteUnsettled(); - - for(Map.Entry entry : unsettledFileNames.entrySet()) - { - if(remoteUnsettled == null || !remoteUnsettled.containsKey(entry.getKey())) - { - - File tmpFile = new File(tmpDirectory, entry.getValue()); - final File dest = new File(directory, - entry.getValue().substring(entry.getValue().indexOf(".") + 1)); - if(dest.exists()) - { - System.err.println("Duplicate detected - filename " + dest.getName()); - } - - tmpFile.renameTo(dest); - } - } - - - int credit = 10; - - r.setCredit(UnsignedInteger.valueOf(credit), true); - - - int received = 0; - Message m = null; - do - { - m = isBlock() && received == 0 ? r.receive() : r.receive(10000); - if(m != null) - { - if(m.isResume() && unsettled.containsKey(m.getDeliveryTag())) - { - final String tmpFileName = unsettledFileNames.get(m.getDeliveryTag()); - final File unsettledFile = new File(tmpDirectory, - tmpFileName); - r.acknowledge(m, new Receiver.SettledAction() - { - public void onSettled(final Binary deliveryTag) - { - int splitPoint = tmpFileName.indexOf("."); - - String fileName = tmpFileName.substring(splitPoint+1); - - final File dest = new File(directory, fileName); - if(dest.exists()) - { - System.err.println("Duplicate detected - filename " + dest.getName()); - } - unsettledFile.renameTo(dest); - unsettledFileNames.remove(deliveryTag); - } - }); - } - else - { - received++; - List
sections = m.getPayload(); - Binary deliveryTag = m.getDeliveryTag(); - StringBuilder tagNameBuilder = new StringBuilder(); - - ByteBuffer dtbuf = deliveryTag.asByteBuffer(); - while(dtbuf.hasRemaining()) - { - tagNameBuilder.append(String.format("%02x", dtbuf.get())); - } - - - ApplicationProperties properties = null; - List data = new ArrayList(); - int totalSize = 0; - for(Section section : sections) - { - if(section instanceof ApplicationProperties) - { - properties = (ApplicationProperties) section; - } - else if(section instanceof AmqpValue) - { - AmqpValue value = (AmqpValue) section; - if(value.getValue() instanceof Binary) - { - Binary binary = (Binary) value.getValue(); - data.add(binary); - totalSize += binary.getLength(); - - } - else - { - // TODO exception - } - } - else if(section instanceof Data) - { - Data value = (Data) section; - Binary binary = value.getValue(); - data.add(binary); - totalSize += binary.getLength(); - - } - } - if(properties != null) - { - final String fileName = (String) properties.getValue().get("filename"); - byte[] fileData = new byte[totalSize]; - ByteBuffer buf = ByteBuffer.wrap(fileData); - int offset = 0; - for(Binary bin : data) - { - buf.put(bin.asByteBuffer()); - } - File outputFile = new File(tmpDirectory, "~"+fileName+"~"); - if(outputFile.exists()) - { - outputFile.delete(); - } - FileOutputStream fos = new FileOutputStream(outputFile); - fos.write(fileData); - fos.flush(); - fos.close(); - - final File unsettledFile = new File(tmpDirectory, tagNameBuilder.toString() + "." + - fileName); - outputFile.renameTo(unsettledFile); - r.acknowledge(m, new Receiver.SettledAction() - { - public void onSettled(final Binary deliveryTag) - { - final File dest = new File(directory, fileName); - if(dest.exists()) - { - System.err.println("Duplicate detected - filename " + dest.getName()); - } - unsettledFile.renameTo(dest); - - } - }); - - } - } - } - } - while(m != null); - - - r.close(); - } - else - { - System.err.println("No such directory: " + directoryName); - } - session.close(); - conn.close(); - } - catch (Connection.ConnectionException e) - { - e.printStackTrace(); - } - catch (FileNotFoundException e) - { - e.printStackTrace(); //TODO. - } - catch (IOException e) - { - e.printStackTrace(); //TODO. - } - catch (AmqpErrorException e) - { - e.printStackTrace(); //TODO. - } - - } - - public static void main(String[] args) - { - new Filereceiver(args).run(); - } -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java deleted file mode 100644 index 46e6ba537f..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Filesender.java +++ /dev/null @@ -1,296 +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.amqp_1_0.client; - -import org.apache.qpid.amqp_1_0.type.Binary; -import org.apache.qpid.amqp_1_0.type.DeliveryState; -import org.apache.qpid.amqp_1_0.type.Outcome; -import org.apache.qpid.amqp_1_0.type.Section; -import org.apache.qpid.amqp_1_0.type.messaging.*; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Options; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.*; - -public class Filesender extends Util -{ - private static final String USAGE_STRING = "filesender [options]
\n\nOptions:"; - - protected Filesender(String[] args) - { - super(args); - } - - @Override - protected boolean hasLinkDurableOption() - { - return true; - } - - @Override - protected boolean hasLinkNameOption() - { - return true; - } - - @Override - protected boolean hasResponseQueueOption() - { - return false; - } - - @Override - protected boolean hasSizeOption() - { - return false; - } - - @Override - protected boolean hasBlockOption() - { - return false; - } - - @Override - protected boolean hasStdInOption() - { - return false; - } - - @Override - protected boolean hasTxnOption() - { - return false; - } - - @Override - protected boolean hasModeOption() - { - return false; - } - - @Override - protected boolean hasCountOption() - { - return false; - } - - @Override - protected void printUsage(Options options) - { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(USAGE_STRING, options ); - - } - - @Override - protected void run() - { - final String queue = getArgs()[0]; - final String directoryName = getArgs()[1]; - - try - { - MessageDigest md5 = MessageDigest.getInstance("MD5"); - Connection conn = newConnection(); - - Session session = conn.createSession(); - - File directory = new File(directoryName); - if(directory.isDirectory() && directory.canWrite()) - { - - File tmpDirectory = new File(directoryName, ".tmp"); - if(!tmpDirectory.exists()) - { - tmpDirectory.mkdir(); - } - - String[] unsettledFiles = tmpDirectory.list(); - - - - Map unsettled = new HashMap(); - Map unsettledFileNames = new HashMap(); - for(String fileName : unsettledFiles) - { - File aFile = new File(tmpDirectory, fileName); - if(aFile.canRead() && aFile.canWrite()) - { - Binary deliveryTag = new Binary(md5.digest(fileName.getBytes())); - unsettled.put(deliveryTag, null); - unsettledFileNames.put(deliveryTag, fileName); - } - } - - - Sender s = session.createSender(queue, 10, AcknowledgeMode.EO, getLinkName(), isDurableLink(), - unsettled); - - Map remoteUnsettled = s.getRemoteUnsettled(); - - for(Map.Entry entry: unsettledFileNames.entrySet()) - { - if(remoteUnsettled == null || !remoteUnsettled.containsKey(entry.getKey())) - { - (new File(tmpDirectory, entry.getValue())).renameTo(new File(directory, entry.getValue())); - } - } - - if(remoteUnsettled != null) - { - for(Map.Entry entry : remoteUnsettled.entrySet()) - { - if(entry.getValue() instanceof Accepted) - { - final String fileName = unsettledFileNames.get(entry.getKey()); - if(fileName != null) - { - - Message resumed = new Message(); - resumed.setDeliveryTag(entry.getKey()); - resumed.setDeliveryState(entry.getValue()); - resumed.setResume(Boolean.TRUE); - resumed.setSettled(Boolean.TRUE); - - - - final File unsettledFile = new File(tmpDirectory, fileName); - unsettledFile.delete(); - - s.send(resumed); - - } - - } - else if(entry.getValue() instanceof Received || entry.getValue() == null) - { - final File unsettledFile = new File(tmpDirectory, unsettledFileNames.get(entry.getKey())); - Message resumed = createMessageFromFile(md5, unsettledFileNames.get(entry.getKey()), unsettledFile); - resumed.setResume(Boolean.TRUE); - Sender.OutcomeAction action = new Sender.OutcomeAction() - { - public void onOutcome(Binary deliveryTag, Outcome outcome) - { - if(outcome instanceof Accepted) - { - unsettledFile.delete(); - } - } - }; - s.send(resumed, action); - - } - } - } - - - - String[] files = directory.list(); - - for(String fileName : files) - { - final File file = new File(directory, fileName); - - if(file.canRead() && file.canWrite() && !file.isDirectory()) - { - Message message = createMessageFromFile(md5, fileName, file); - - final File unsettledFile = new File(tmpDirectory, fileName); - - Sender.OutcomeAction action = new Sender.OutcomeAction() - { - public void onOutcome(Binary deliveryTag, Outcome outcome) - { - if(outcome instanceof Accepted) - { - unsettledFile.delete(); - } - } - }; - - file.renameTo(unsettledFile); - - s.send(message, action); - } - } - - s.close(); - } - else - { - System.err.println("No such directory: " + directory); - } - session.close(); - conn.close(); - } - catch (Connection.ConnectionException e) - { - e.printStackTrace(); - } - catch (Sender.SenderCreationException e) - { - e.printStackTrace(); - } catch (FileNotFoundException e) - { - e.printStackTrace(); - } catch (IOException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } catch (NoSuchAlgorithmException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } catch (Sender.SenderClosingException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - - } - - private Message createMessageFromFile(MessageDigest md5, String fileName, File file) throws IOException - { - FileInputStream fis = new FileInputStream(file); - byte[] data = new byte[(int) file.length()]; - - int read = fis.read(data); - - fis.close(); - - Section applicationProperties = new ApplicationProperties(Collections.singletonMap("filename", fileName)); - Section amqpValue = new Data(new Binary(data)); - Message message = new Message(Arrays.asList(applicationProperties, amqpValue)); - Binary deliveryTag = new Binary(md5.digest(fileName.getBytes())); - message.setDeliveryTag(deliveryTag); - md5.reset(); - return message; - } - - public static void main(String[] args) - { - new Filesender(args).run(); - } -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/ReadBytes.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/ReadBytes.java deleted file mode 100644 index 07ae54b54f..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/ReadBytes.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.qpid.amqp_1_0.client; - -import org.apache.qpid.amqp_1_0.codec.ValueHandler; -import org.apache.qpid.amqp_1_0.type.AmqpErrorException; -import org.apache.qpid.amqp_1_0.type.codec.AMQPDescribedTypeRegistry; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; - -public class ReadBytes -{ - - public static void main(String[] args) throws IOException, AmqpErrorException - { - - if(args.length == 0) - { - readBytes(System.in); - } - else - { - for(String fileName : args) - { - System.out.println("=========================== " + fileName + " ==========================="); - final FileInputStream fis = new FileInputStream(fileName); - readBytes(fis); - fis.close(); - } - } - - } - - private static void readBytes(final InputStream inputStream) throws IOException, AmqpErrorException - { - byte[] bytes = new byte[4096]; - - ValueHandler valueHandler = new ValueHandler(AMQPDescribedTypeRegistry.newInstance()); - - int count; - - while((count = inputStream.read(bytes))!=-1) - { - ByteBuffer buf = ByteBuffer.wrap(bytes); - buf.limit(count); - while(buf.hasRemaining()) - { - - final Object value = valueHandler.parse(buf); - System.out.print((value == null ? "" : value.getClass().getName() + ":") +value +"\n"); - - } - } - - } - - -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receive.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receive.java deleted file mode 100644 index 0da9dc3fb7..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receive.java +++ /dev/null @@ -1,246 +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.amqp_1_0.client; - -import org.apache.qpid.amqp_1_0.type.AmqpErrorException; -import org.apache.qpid.amqp_1_0.type.Symbol; -import org.apache.qpid.amqp_1_0.type.UnsignedInteger; -import org.apache.qpid.amqp_1_0.type.UnsignedLong; -import org.apache.commons.cli.*; -import org.apache.qpid.amqp_1_0.type.messaging.ExactSubjectFilter; -import org.apache.qpid.amqp_1_0.type.messaging.Filter; -import org.apache.qpid.amqp_1_0.type.messaging.MatchingSubjectFilter; - -import java.util.Collections; - -public class Receive extends Util -{ - private static final String USAGE_STRING = "receive [options]
\n\nOptions:"; - private static final UnsignedLong UNSIGNED_LONG_ONE = UnsignedLong.valueOf(1L); - private UnsignedLong _lastCorrelationId; - - public static void main(String[] args) - { - new Receive(args).run(); - } - - - public Receive(final String[] args) - { - super(args); - } - - @Override - protected boolean hasLinkDurableOption() - { - return true; - } - - @Override - protected boolean hasLinkNameOption() - { - return true; - } - - @Override - protected boolean hasResponseQueueOption() - { - return false; - } - - @Override - protected boolean hasSizeOption() - { - return false; - } - - @Override - protected boolean hasBlockOption() - { - return true; - } - - @Override - protected boolean hasStdInOption() - { - return true; - } - - @Override - protected boolean hasTxnOption() - { - return true; - } - - @Override - protected boolean hasModeOption() - { - return true; - } - - @Override - protected boolean hasCountOption() - { - return true; - } - - @Override - protected boolean hasWindowSizeOption() - { - return true; - } - - @Override - protected boolean hasFilterOption() - { - return true; - } - - protected void run() - { - - try - { - final String queue = getArgs()[0]; - - String message = ""; - - Connection conn = newConnection(); - - - Session session = conn.createSession(); - - Filter filter = null; - if(getFilter() != null) - { - String[] filterParts = getFilter().split("=",2); - if("exact-subject".equals(filterParts[0])) - { - filter = new ExactSubjectFilter(filterParts[1]); - } - else if("matching-subject".equals(filterParts[0])) - { - filter = new MatchingSubjectFilter(filterParts[1]); - } - else - { - System.err.println("Unknown filter type: " + filterParts[0]); - } - } - - Receiver r = - filter == null - ? session.createReceiver(queue, getMode(), getLinkName(), isDurableLink()) - : session.createReceiver(queue, getMode(), getLinkName(), isDurableLink(), Collections.singletonMap(Symbol.valueOf("filter"), filter), null); - Transaction txn = null; - - int credit = 0; - int receivedCount = 0; - - if(!useStdIn()) - { - if(getArgs().length <= 2) - { - - Transaction txn2 = null; - if(useTran()) - { - txn = session.createSessionLocalTransaction(); - txn2 = session.createSessionLocalTransaction(); - } - - for(int i = 0; i < getCount(); i++) - { - - if(credit == 0) - { - if(getCount() - i <= getWindowSize()) - { - credit = getCount() - i; - - } - else - { - credit = getWindowSize(); - - } - - { - r.setCredit(UnsignedInteger.valueOf(credit), false); - } - if(!isBlock()) - r.drain(); - } - - Message m = isBlock() ? r.receive() : r.receive(1000L); - credit--; - if(m==null) - { - break; - } - - - - r.acknowledge(m.getDeliveryTag(),txn); - - receivedCount++; - - System.out.println("Received Message : " + m.getPayload()); - } - - if(useTran()) - { - txn.commit(); - } - } - else - { - // TODO - } - } - else - { - // TODO - } - r.close(); - session.close(); - conn.close(); - System.out.println("Total Messages Received: " + receivedCount); - } - catch (Connection.ConnectionException e) - { - e.printStackTrace(); //TODO. - } - catch (AmqpErrorException e) - { - e.printStackTrace(); //TODO. - } - - } - - protected void printUsage(Options options) - { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(USAGE_STRING, options ); - } - -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java index ad390fd498..8b792db1f1 100644 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java +++ b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java @@ -241,7 +241,7 @@ public class Receiver implements DeliveryStateHandler } if(hasMore) { - xfr = receiveFromPrefetch(0L); + xfr = receiveFromPrefetch(-1l); if(xfr== null) { // TODO - this is wrong!!!! @@ -503,6 +503,37 @@ public class Receiver implements DeliveryStateHandler _endpoint.drain(); } + /** + * Waits for the receiver to drain or a message to be available to be received. + * @return true if the receiver has been drained. + */ + public boolean drainWait() + { + final Object lock = _endpoint.getLock(); + synchronized(lock) + { + try + { + while( _prefetchQueue.peek()==null && !_endpoint.isDrained() && !_endpoint.isDetached() ) + { + lock.wait(); + } + } + catch (InterruptedException e) + { + } + } + return _prefetchQueue.peek()==null && _endpoint.isDrained(); + } + + /** + * Clears the receiver drain so that message delivery can resume. + */ + public void clearDrain() + { + _endpoint.clearDrain(); + } + public void setCreditWithTransaction(final UnsignedInteger credit, final Transaction txn) { _endpoint.setLinkCredit(credit); @@ -558,4 +589,4 @@ public class Receiver implements DeliveryStateHandler void messageArrived(Receiver receiver); } -} \ No newline at end of file +} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Request.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Request.java deleted file mode 100644 index 6e1d15376c..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Request.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.amqp_1_0.client; - -import org.apache.qpid.amqp_1_0.type.AmqpErrorException; -import org.apache.qpid.amqp_1_0.type.Section; -import org.apache.qpid.amqp_1_0.type.UnsignedInteger; -import org.apache.qpid.amqp_1_0.type.UnsignedLong; -import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; -import org.apache.qpid.amqp_1_0.type.messaging.Header; -import org.apache.qpid.amqp_1_0.type.messaging.Properties; -import org.apache.commons.cli.*; - -import java.util.Arrays; - -public class Request extends Util -{ - private static final String USAGE_STRING = "request [options]
[ ...]\n\nOptions:"; - - public static void main(String[] args) - { - new Request(args).run(); - } - - public Request(String[] args) - { - super(args); - } - - @Override - protected boolean hasLinkDurableOption() - { - return false; - } - - @Override - protected boolean hasLinkNameOption() - { - return false; - } - - @Override - protected boolean hasResponseQueueOption() - { - return false; - } - - @Override - protected boolean hasSizeOption() - { - return true; - } - - @Override - protected boolean hasBlockOption() - { - return false; - } - - @Override - protected boolean hasStdInOption() - { - return false; - } - - @Override - protected boolean hasTxnOption() - { - return true; - } - - @Override - protected boolean hasModeOption() - { - return true; - } - - @Override - protected boolean hasCountOption() - { - return true; - } - - @Override - protected boolean hasWindowSizeOption() - { - return true; - } - - public void run() - { - - try - { - - - final String queue = getArgs()[0]; - - String message = ""; - - Connection conn = newConnection(); - Session session = conn.createSession(); - - Connection conn2; - Session session2; - Receiver responseReceiver; - - if(isUseMultipleConnections()) - { - conn2 = newConnection(); - session2 = conn2.createSession(); - responseReceiver = session2.createTemporaryQueueReceiver(); - } - else - { - conn2 = null; - session2 = null; - responseReceiver = session.createTemporaryQueueReceiver(); - } - - - - - responseReceiver.setCredit(UnsignedInteger.valueOf(getWindowSize()), true); - - - - Sender s = session.createSender(queue, getWindowSize(), getMode()); - - Transaction txn = null; - - if(useTran()) - { - txn = session.createSessionLocalTransaction(); - } - - int received = 0; - - if(getArgs().length >= 2) - { - message = getArgs()[1]; - if(message.length() < getMessageSize()) - { - StringBuilder builder = new StringBuilder(getMessageSize()); - builder.append(message); - for(int x = message.length(); x < getMessageSize(); x++) - { - builder.append('.'); - } - message = builder.toString(); - } - - for(int i = 0; i < getCount(); i++) - { - Properties properties = new Properties(); - properties.setMessageId(UnsignedLong.valueOf(i)); - properties.setReplyTo(responseReceiver.getAddress()); - - AmqpValue amqpValue = new AmqpValue(message); - Section[] sections = { new Header() , properties, amqpValue}; - final Message message1 = new Message(Arrays.asList(sections)); - - s.send(message1, txn); - - Message responseMessage = responseReceiver.receive(false); - if(responseMessage != null) - { - responseReceiver.acknowledge(responseMessage.getDeliveryTag(),txn); - received++; - } - } - } - - if(txn != null) - { - txn.commit(); - } - - - while(received < getCount()) - { - Message responseMessage = responseReceiver.receive(); - responseReceiver.acknowledge(responseMessage.getDeliveryTag()); - received++; - } - - - - - s.close(); - session.close(); - conn.close(); - - if(session2 != null) - { - session2.close(); - conn2.close(); - } - } - catch (Connection.ConnectionException e) - { - e.printStackTrace(); //TODO. - } - catch (Sender.SenderClosingException e) - { - e.printStackTrace(); //TODO. - } - catch (Sender.SenderCreationException e) - { - e.printStackTrace(); //TODO. - } - catch (AmqpErrorException e) - { - e.printStackTrace(); //TODO. - } - - } - - protected boolean hasSingleLinkPerConnectionMode() - { - return true; - } - - protected void printUsage(Options options) - { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(USAGE_STRING, options ); - } - -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java deleted file mode 100644 index 8d9de4893f..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.amqp_1_0.client; - -import org.apache.qpid.amqp_1_0.type.AmqpErrorException; -import org.apache.qpid.amqp_1_0.type.Section; -import org.apache.qpid.amqp_1_0.type.UnsignedInteger; -import org.apache.qpid.amqp_1_0.type.UnsignedLong; -import org.apache.qpid.amqp_1_0.type.messaging.Properties; -import org.apache.commons.cli.*; - -import java.util.*; - -public class Respond extends Util -{ - private static final String USAGE_STRING = "respond [options]
\n\nOptions:"; - private Connection _conn; - private Session _session; - private Receiver _receiver; - private Transaction _txn; - private Map _senders; - private UnsignedLong _responseMsgId = UnsignedLong.ZERO; - private Connection _conn2; - private Session _session2; - - public Respond(final String[] args) - { - super(args); - } - - @Override - protected boolean hasLinkDurableOption() - { - return false; - } - - @Override - protected boolean hasLinkNameOption() - { - return false; - } - - @Override - protected boolean hasResponseQueueOption() - { - return true; - } - - @Override - protected boolean hasSizeOption() - { - return false; - } - - @Override - protected boolean hasBlockOption() - { - return true; - } - - @Override - protected boolean hasStdInOption() - { - return false; - } - - @Override - protected boolean hasTxnOption() - { - return true; - } - - @Override - protected boolean hasModeOption() - { - return true; - } - - @Override - protected boolean hasCountOption() - { - return true; - } - - @Override - protected boolean hasSingleLinkPerConnectionMode() - { - return true; - } - - - @Override - protected boolean hasWindowSizeOption() - { - return true; - } - - public static void main(String[] args) - { - new Respond(args).run(); - } - - public void run() - { - try - { - - _senders = new HashMap(); - - final String queue = getArgs()[0]; - - String message = ""; - - _conn = newConnection(); - - - - if(isUseMultipleConnections()) - { - _conn2 = newConnection(); - _session2 = _conn2.createSession(); - } - - - _session = _conn.createSession(); - - - _receiver = _session.createReceiver(queue, getMode()); - _txn = null; - - int credit = 0; - int receivedCount = 0; - _responseMsgId = UnsignedLong.ZERO; - - Random random = null; - int batch = 0; - List txnMessages = null; - if(useTran()) - { - if(getRollbackRatio() != 0) - { - random = new Random(); - } - batch = getBatchSize(); - _txn = _session.createSessionLocalTransaction(); - txnMessages = new ArrayList(batch); - } - - - for(int i = 0; receivedCount < getCount(); i++) - { - - if(credit == 0) - { - if(getCount() - i <= getWindowSize()) - { - credit = getCount() - i; - - } - else - { - credit = getWindowSize(); - - } - - _receiver.setCredit(UnsignedInteger.valueOf(credit), false); - - if(!isBlock()) - _receiver.drain(); - } - - Message m = isBlock() ? (receivedCount == 0 ? _receiver.receive() : _receiver.receive(10000L)) : _receiver.receive(1000L); - credit--; - if(m==null) - { - if(useTran() && batch != getBatchSize()) - { - _txn.commit(); - } - break; - } - - System.out.println("Received Message: " + m.getPayload()); - - respond(m); - - - - if(useTran()) - { - - txnMessages.add(m); - - if(--batch == 0) - { - - if(getRollbackRatio() == 0 || random.nextDouble() >= getRollbackRatio()) - { - _txn.commit(); - txnMessages.clear(); - receivedCount += getBatchSize(); - } - else - { - System.out.println("Random Rollback"); - _txn.rollback(); - double result; - do - { - _txn = _session.createSessionLocalTransaction(); - - for(Message msg : txnMessages) - { - respond(msg); - } - - result = random.nextDouble(); - if(result sections = m.getPayload(); - String replyTo = null; - Object correlationId = null; - for(Section section : sections) - { - if(section instanceof Properties) - { - replyTo = getResponseQueue() == null ? ((Properties)section).getReplyTo() : getResponseQueue(); - correlationId = ((Properties) section).getMessageId(); - break; - } - } - - if(replyTo != null) - { - Sender s = _senders.get(replyTo); - if(s == null) - { - s = (isUseMultipleConnections() ? _session2 : _session).createSender(replyTo,getWindowSize()); - _senders.put(replyTo, s); - } - - List
replySections = new ArrayList
(sections); - - ListIterator
sectionIterator = replySections.listIterator(); - - while(sectionIterator.hasNext()) - { - Section section = sectionIterator.next(); - if(section instanceof Properties) - { - Properties newProps = new Properties(); - newProps.setTo(replyTo); - newProps.setCorrelationId(correlationId); - newProps.setMessageId(_responseMsgId); - _responseMsgId = _responseMsgId.add(UnsignedLong.ONE); - sectionIterator.set(newProps); - } - } - - Message replyMessage = new Message(replySections); - System.out.println("Sent Message: " + replySections); - s.send(replyMessage, _txn); - - } - _receiver.acknowledge(m.getDeliveryTag(), _txn); - } - - protected void printUsage(Options options) - { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(USAGE_STRING, options ); - } - -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Send.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Send.java deleted file mode 100644 index 6f6575e083..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Send.java +++ /dev/null @@ -1,244 +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.amqp_1_0.client; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.util.Arrays; - -import org.apache.qpid.amqp_1_0.type.Binary; -import org.apache.qpid.amqp_1_0.type.Section; -import org.apache.qpid.amqp_1_0.type.UnsignedLong; -import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; -import org.apache.qpid.amqp_1_0.type.messaging.Data; -import org.apache.qpid.amqp_1_0.type.messaging.Properties; -import org.apache.commons.cli.*; - -public class Send extends Util -{ - private static final String USAGE_STRING = "send [options]
[ ...]\n\nOptions:"; - private static final char[] HEX = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; - - - public static void main(String[] args) throws Sender.SenderCreationException, Sender.SenderClosingException, Connection.ConnectionException - { - new Send(args).run(); - } - - - public Send(final String[] args) - { - super(args); - } - - @Override - protected boolean hasLinkDurableOption() - { - return true; - } - - @Override - protected boolean hasLinkNameOption() - { - return true; - } - - @Override - protected boolean hasResponseQueueOption() - { - return false; - } - - @Override - protected boolean hasSizeOption() - { - return true; - } - - @Override - protected boolean hasBlockOption() - { - return false; - } - - @Override - protected boolean hasStdInOption() - { - return true; - } - - @Override - protected boolean hasTxnOption() - { - return true; - } - - @Override - protected boolean hasModeOption() - { - return true; - } - - @Override - protected boolean hasCountOption() - { - return true; - } - - @Override - protected boolean hasWindowSizeOption() - { - return true; - } - - @Override - protected boolean hasSubjectOption() - { - return true; - } - - public void run() - { - - final String queue = getArgs()[0]; - - String message = ""; - - try - { - Connection conn = newConnection(); - - Session session = conn.createSession(); - - - Sender s = session.createSender(queue, getWindowSize(), getMode(), getLinkName()); - - Transaction txn = null; - - if(useTran()) - { - txn = session.createSessionLocalTransaction(); - } - - if(!useStdIn()) - { - if(getArgs().length <= 2) - { - if(getArgs().length == 2) - { - message = getArgs()[1]; - } - for(int i = 0; i < getCount(); i++) - { - - Properties properties = new Properties(); - properties.setMessageId(UnsignedLong.valueOf(i)); - if(getSubject() != null) - { - properties.setSubject(getSubject()); - } - Section bodySection; - byte[] bytes = (message + " " + i).getBytes(); - if(bytes.length < getMessageSize()) - { - byte[] origBytes = bytes; - bytes = new byte[getMessageSize()]; - System.arraycopy(origBytes,0,bytes,0,origBytes.length); - for(int x = origBytes.length; x < bytes.length; x++) - { - bytes[x] = (byte) '.'; - } - bodySection = new Data(new Binary(bytes)); - } - else - { - bodySection = new AmqpValue(message + " " + i); - } - - Section[] sections = {properties, bodySection}; - final Message message1 = new Message(Arrays.asList(sections)); - - s.send(message1, txn); - } - } - else - { - for(int i = 1; i < getArgs().length; i++) - { - s.send(new Message(getArgs()[i]), txn); - } - - } - } - else - { - LineNumberReader buf = new LineNumberReader(new InputStreamReader(System.in)); - - - try - { - while((message = buf.readLine()) != null) - { - s.send(new Message(message), txn); - } - } - catch (IOException e) - { - // TODO - e.printStackTrace(); - } - } - - if(txn != null) - { - txn.commit(); - } - - s.close(); - - session.close(); - conn.close(); - } - catch (Sender.SenderClosingException e) - { - e.printStackTrace(); //TODO. - } - catch (Connection.ConnectionException e) - { - e.printStackTrace(); //TODO. - } - catch (Sender.SenderCreationException e) - { - e.printStackTrace(); //TODO. - } - - - } - - protected void printUsage(Options options) - { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp(USAGE_STRING, options ); - } - -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SendBytes.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SendBytes.java deleted file mode 100644 index 6f97ecd810..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SendBytes.java +++ /dev/null @@ -1,331 +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.amqp_1_0.client; - -import org.apache.qpid.amqp_1_0.codec.FrameWriter; -import org.apache.qpid.amqp_1_0.codec.ValueWriter; -import org.apache.qpid.amqp_1_0.framing.AMQFrame; -import org.apache.qpid.amqp_1_0.type.Binary; -import org.apache.qpid.amqp_1_0.type.FrameBody; -import org.apache.qpid.amqp_1_0.type.Section; -import org.apache.qpid.amqp_1_0.type.Symbol; -import org.apache.qpid.amqp_1_0.type.UnsignedByte; -import org.apache.qpid.amqp_1_0.type.UnsignedInteger; -import org.apache.qpid.amqp_1_0.type.UnsignedLong; -import org.apache.qpid.amqp_1_0.type.UnsignedShort; -import org.apache.qpid.amqp_1_0.type.codec.AMQPDescribedTypeRegistry; -import org.apache.qpid.amqp_1_0.type.messaging.Footer; -import org.apache.qpid.amqp_1_0.type.messaging.Header; -import org.apache.qpid.amqp_1_0.type.messaging.Properties; -import org.apache.qpid.amqp_1_0.type.transport.Flow; - -import org.apache.qpid.amqp_1_0.type.transport.Transfer; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - -public class SendBytes -{ - - public static void main(String[] args) throws - Sender.SenderCreationException, - Sender.SenderClosingException, - Connection.ConnectionException, - IOException, ParseException - { - Transfer xfr = new Transfer(); - Flow fs = new Flow(); - fs.setIncomingWindow(UnsignedInteger.valueOf(1024)); - fs.setDeliveryCount(UnsignedInteger.valueOf(2)); - fs.setLinkCredit(UnsignedInteger.valueOf(18)); - fs.setAvailable(UnsignedInteger.valueOf(0)); - fs.setDrain(false); - - xfr.setHandle(UnsignedInteger.valueOf(0)); - xfr.setDeliveryTag(new Binary("\"queue\"<-6ec024a7-d98e-4196-9348-15f6026c32ca:0".getBytes())); - //xfr.setDeliveryTag(new Binary(new byte[] {0})); - xfr.setDeliveryId(UnsignedInteger.valueOf(0)); - xfr.setSettled(true); - - - Header h = new Header(); - Properties p = new Properties(); - p.setTo("queue"); - //p.setMessageId(new Binary(UUID.randomUUID().toString().getBytes())); - - Footer f = new Footer(Collections.EMPTY_MAP); - - Section[] sections = new Section[] { h,p,f}; - //Section[] sections = new Section[] { b }; - //Section[] sections = { h,p, b}; -/* - Fragment[] fragments = new Fragment[5]; - - final AMQPDescribedTypeRegistry typeRegistry = AMQPDescribedTypeRegistry.newInstance().registerTransportLayer().registerMessagingLayer(); - - SectionEncoderImpl encoder = new SectionEncoderImpl(typeRegistry); - - int num = 0; - int i = 0; - for(Section s : sections) - { - Fragment frag = new Fragment(); - - frag.setPayload(s.encode(encoder)); - frag.setFirst(true); - frag.setLast(true); - frag.setSectionCode(s.getSectionCode()); - frag.setSectionNumber(UnsignedInteger.valueOf(num++)); - frag.setSectionOffset(UnsignedLong.valueOf(0L)); - fragments[i++] =frag; - } - - xfr.setFragments(fragments); -*/ - - encodeTypes("xfr",xfr); - - final byte[] result; - final Object input = xfr; -/* - result = encode(1024, input); - - boolean ok = true; - - for(int j = 10; ok && j < 400; j++) - { - - byte[] result2 = encode(j,input); - - for(int i = 0; i <400; i++) - { - if(result[i] != result2[i]) - { - System.out.println("result differs at " + i + " Splitting at " + j+ " [" + result[i] + " - " + result2[i] + "]"); - //break; - //ok = false; - - } - } - }*/ - //System.out.println(Arrays.equals(result, result2)); - - //doEncodes(); - /*OutputStream out = System.out; - if(args.length > 0) - { - out = new FileOutputStream(args[0]); - } - - Transfer xfr = new Transfer(); - fs.setSessionCredit(UnsignedInteger.valueOf(1024)); - fs.setTransferCount(UnsignedInteger.valueOf(2)); - fs.setLinkCredit(UnsignedInteger.valueOf(18)); - fs.setAvailable(UnsignedInteger.valueOf(0)); - fs.setDrain(false); - - xfr.setHandle(UnsignedInteger.valueOf(0)); - //xfr.setDeliveryTag(new Binary("\"queue\"<-6ec024a7-d98e-4196-9348-15f6026c32ca:0".getBytes())); - xfr.setDeliveryTag(new Binary(new byte[] {0})); - xfr.setTransferId(UnsignedInteger.valueOf(0)); - xfr.setSettled(true); - xfr.setFlowState(fs); - - Header h = new Header(); - h.setTransmitTime(new Date(System.currentTimeMillis())); - Properties p = new Properties(); - p.setTo(new Address("queue")); - //p.setMessageId(new Binary(UUID.randomUUID().toString().getBytes())); - AmqpMapSection m = new AmqpMapSection(); - DataSection b = new DataSection("Hello World!".getBytes()); - - Footer f = new Footer(); - - Section[] sections = new Section[] { h,p,m,b,f}; - //Section[] sections = new Section[] { b }; - //Section[] sections = { h,p, b}; - List fragments = new ArrayList(5); - - final AMQPDescribedTypeRegistry typeRegistry = AMQPDescribedTypeRegistry.newInstance(); - - SectionEncoderImpl encoder = new SectionEncoderImpl(typeRegistry); - - for(Section s : sections) - { - Fragment frag = new Fragment(); - - frag.setPayload(s.encode(encoder)); - frag.setFirst(true); - frag.setLast(true); - frag.setFormatCode(s.getSectionCode()); - frag.setFragmentOffset(null); - fragments.add(frag); - } - - xfr.setFragments(fragments); - - - Object[] objectsToWrite = new Object[] { xfr }; - ByteBuffer buf = ByteBuffer.allocate(4096); - - - for(Object obj : objectsToWrite) - { - ValueWriter writer = typeRegistry.getValueWriter(obj); - - int count; - - - do - { - count = writer.writeToBuffer(buf); - out.write(buf.array(), buf.arrayOffset(), count); - buf.clear(); - } while (!writer.isComplete()); - - } - - out.flush(); - out.close();*/ - - } - - public static void doEncodes() throws IOException, ParseException - { - encodeTypes("boolean", Boolean.TRUE, Boolean.FALSE); - encodeTypes("ubyte", UnsignedByte.valueOf((byte)0), UnsignedByte.valueOf((byte)1 ),UnsignedByte.valueOf((byte)3), UnsignedByte.valueOf((byte)42), UnsignedByte.valueOf("255")); - encodeTypes("byte", Byte.valueOf((byte)0), Byte.valueOf( (byte)1), Byte.valueOf((byte) 3), Byte.valueOf((byte) 42), Byte.valueOf((byte) 127), Byte.valueOf((byte) -1), Byte.valueOf((byte) -3), Byte.valueOf((byte) -42), Byte.valueOf( (byte)-128)); - encodeTypes("ushort", UnsignedShort.valueOf((short)0), UnsignedShort.valueOf((short)1), UnsignedShort.valueOf((short)3), UnsignedShort.valueOf((short)42), UnsignedShort.valueOf("65535")); - encodeTypes("short", Short.valueOf((short)0), Short.valueOf((short)1), Short.valueOf((short)3), Short.valueOf((short)42), Short.valueOf((short)32767), Short.valueOf((short)-1), Short.valueOf((short)-3), Short.valueOf((short)-42), Short.valueOf((short)-32768)); - encodeTypes("uint",UnsignedInteger.valueOf(0), UnsignedInteger.valueOf(1), UnsignedInteger.valueOf(3), UnsignedInteger.valueOf(42), UnsignedInteger.valueOf("4294967295")); - encodeTypes("int", 0, 1, 3, 42, 2147483647, -1, -3, -42, -2147483648); - encodeTypes("ulong", UnsignedLong.valueOf(0), UnsignedLong.valueOf(1), UnsignedLong.valueOf(3), UnsignedLong.valueOf(42), UnsignedLong.valueOf("18446744073709551615")); - encodeTypes("long", 0l, 1l, 3l, 42l, 9223372036854775807l, -1l, -3l, -42l, -9223372036854775808l); - encodeTypes("float", 3.14159); - encodeTypes("double", Double.valueOf(3.14159265359)); - encodeTypes("char", '?'); - - SimpleDateFormat df = new SimpleDateFormat("HHa z MMM d yyyy"); - - encodeTypes("timestamp", df.parse("9AM PST Dec 6 2010"), df.parse("9AM PST Dec 6 1910")); - encodeTypes("uuid", UUID.fromString("f275ea5e-0c57-4ad7-b11a-b20c563d3b71")); - encodeTypes("binary", new Binary( new byte[] {(byte)0xDE, (byte)0xAD, (byte)0xBE, (byte)0xEF}), new Binary(new byte[] { (byte)0xCA,(byte)0xFE, (byte)0xBA, (byte)0xBE})); - encodeTypes("string", "The quick brown fox jumped over the lazy cow."); - encodeTypes("symbol", Symbol.valueOf("connectathon")); - encodeTypes("list", Arrays.asList(new Object[] {Long.valueOf(1), "two", Double.valueOf(3.14159265359), null, Boolean.FALSE})); - Map map = new HashMap(); - map.put("one", Long.valueOf(1)); - map.put("two", Long.valueOf(2)); - map.put("pi", Double.valueOf(3.14159265359)); - map.put("list:", Arrays.asList(new Object[] {Long.valueOf(1), "two", Double.valueOf(3.14159265359), null, Boolean.FALSE})); - map.put(null, Boolean.TRUE); - encodeTypes("map", map); - encodeTypes("null", null); - - } - - static void encodeTypes(String name, Object... vals ) throws IOException - { - FileOutputStream out = new FileOutputStream("/home/rob/"+name+".out"); - ByteBuffer buf = ByteBuffer.allocate(4096); - final AMQPDescribedTypeRegistry typeRegistry = AMQPDescribedTypeRegistry.newInstance(); - - if(vals != null) - { - for(Object obj : vals) - { - ValueWriter writer = typeRegistry.getValueWriter(obj); - - int count; - - - do - { - count = writer.writeToBuffer(buf); - out.write(buf.array(), buf.arrayOffset(), count); - buf.clear(); - } while (!writer.isComplete()); - - } - } - else - { - ValueWriter writer = typeRegistry.getValueWriter(null); - - int count; - - - do - { - count = writer.writeToBuffer(buf); - out.write(buf.array(), buf.arrayOffset(), count); - buf.clear(); - } while (!writer.isComplete()); - - } - out.flush(); - out.close(); - - } - - static byte[] encode(int size, Object... vals) - { - byte[] result = new byte[10000]; - int pos = 0; - - final AMQPDescribedTypeRegistry typeRegistry = AMQPDescribedTypeRegistry.newInstance(); - AMQFrame frame = AMQFrame.createAMQFrame((short) 0, (FrameBody) vals[0]); - FrameWriter writer = new FrameWriter(typeRegistry); - /*for(Object obj : vals) - { - final AMQPDescribedTypeRegistry typeRegistry = AMQPDescribedTypeRegistry.newInstance(); - ValueWriter writer = typeRegistry.getValueWriter(obj); -*/ - int count; - - ByteBuffer buf = ByteBuffer.wrap(result, pos, size); - - do - { - - writer.writeToBuffer(buf); - pos = buf.position(); - buf = ByteBuffer.wrap(result, pos, size); - if(!writer.isComplete()) - { - count = 3; - } - - } while (!writer.isComplete()); -/* - - } -*/ - - return result; - - } - - -} diff --git a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Util.java b/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Util.java deleted file mode 100644 index 6fe2a6d510..0000000000 --- a/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Util.java +++ /dev/null @@ -1,529 +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.amqp_1_0.client; - -import org.apache.qpid.amqp_1_0.transport.Container; -import org.apache.commons.cli.*; - -import java.util.logging.*; - -public abstract class Util -{ - - private static final Logger FRAME_LOGGER = Logger.getLogger("FRM"); - private static final Logger RAW_LOGGER = Logger.getLogger("RAW"); - private String _host; - private String _username; - private String _password; - private int _port; - private int _count; - private boolean _useStdIn; - private boolean _useTran; - private String[] _args; - private AcknowledgeMode _mode; - private boolean _block; - private int _frameSize; - private int _messageSize; - private String _responseQueue; - private int _batchSize; - private double _rollbackRatio; - private String _linkName; - private String _containerName; - private boolean _durableLink; - private boolean _useMultipleConnections; - private int _windowSize = 100; - private String _subject; - private String _filter; - private String _remoteHost; - private boolean _useSSL; - - protected Util(String[] args) - { - CommandLineParser cmdLineParse = new PosixParser(); - - Options options = new Options(); - options.addOption("h","help",false,"show this help message and exit"); - options.addOption(OptionBuilder.withLongOpt("host") - .withDescription( "host to connect to (default 0.0.0.0)" ) - .hasArg(true) - .withArgName("HOST") - .create('H')); - options.addOption(OptionBuilder.withLongOpt("username") - .withDescription( "username to use for authentication" ) - .hasArg(true) - .withArgName("USERNAME") - .create('u')); - options.addOption(OptionBuilder.withLongOpt("password") - .withDescription( "password to use for authentication" ) - .hasArg(true) - .withArgName("PASSWORD") - .create('w')); - options.addOption(OptionBuilder.withLongOpt("port") - .withDescription( "port to connect to (default 5672)" ) - .hasArg(true) - .withArgName("PORT") - .create('p')); - options.addOption(OptionBuilder.withLongOpt("frame-size") - .withDescription( "specify the maximum frame size" ) - .hasArg(true) - .withArgName("FRAME_SIZE") - .create('f')); - options.addOption(OptionBuilder.withLongOpt("container-name") - .withDescription( "Container name" ) - .hasArg(true) - .withArgName("CONTAINER_NAME") - .create('C')); - - options.addOption(OptionBuilder.withLongOpt("ssl") - .withDescription("Use SSL") - .create('S')); - - options.addOption(OptionBuilder.withLongOpt("remote-hostname") - .withDescription( "hostname to supply in the open frame" ) - .hasArg(true) - .withArgName("HOST") - .create('O')); - - if(hasBlockOption()) - options.addOption(OptionBuilder.withLongOpt("block") - .withDescription("block until messages arrive") - .create('b')); - - if(hasCountOption()) - options.addOption(OptionBuilder.withLongOpt("count") - .withDescription( "number of messages to send (default 1)" ) - .hasArg(true) - .withArgName("COUNT") - .create('c')); - if(hasModeOption()) - options.addOption(OptionBuilder.withLongOpt("acknowledge-mode") - .withDescription( "acknowledgement mode: AMO|ALO|EO (At Least Once, At Most Once, Exactly Once" ) - .hasArg(true) - .withArgName("MODE") - .create('k')); - - if(hasSubjectOption()) - options.addOption(OptionBuilder.withLongOpt("subject") - .withDescription( "subject message property" ) - .hasArg(true) - .withArgName("SUBJECT") - .create('s')); - - - if(hasSingleLinkPerConnectionMode()) - options.addOption(OptionBuilder.withLongOpt("single-link-per-connection") - .withDescription("acknowledgement mode: AMO|ALO|EO (At Least Once, At Most Once, Exactly Once") - .hasArg(false) - .create('Z')); - - if(hasFilterOption()) - options.addOption(OptionBuilder.withLongOpt("filter") - .withDescription("filter, e.g. exact-subject=hello; matching-subject=%.a.#") - .hasArg(true) - .withArgName("=") - .create('F')); - - - if(hasTxnOption()) - { - options.addOption("x","txn",false,"use transactions"); - options.addOption(OptionBuilder.withLongOpt("batch-size") - .withDescription( "transaction batch size (default: 1)" ) - .hasArg(true) - .withArgName("BATCH-SIZE") - .create('B')); - options.addOption(OptionBuilder.withLongOpt("rollback-ratio") - .withDescription( "rollback ratio - must be between 0 and 1 (default: 0)" ) - .hasArg(true) - .withArgName("RATIO") - .create('R')); - } - - if(hasLinkDurableOption()) - { - options.addOption("d","durable-link",false,"use a durable link"); - } - - if(hasStdInOption()) - options.addOption("i","stdin",false,"read messages from stdin (one message per line)"); - - options.addOption(OptionBuilder.withLongOpt("trace") - .withDescription("trace logging specified categories: RAW, FRM") - .hasArg(true) - .withArgName("TRACE") - .create('t')); - if(hasSizeOption()) - options.addOption(OptionBuilder.withLongOpt("message-size") - .withDescription( "size to pad outgoing messages to" ) - .hasArg(true) - .withArgName("SIZE") - .create('z')); - - if(hasResponseQueueOption()) - options.addOption(OptionBuilder.withLongOpt("response-queue") - .withDescription( "response queue to reply to" ) - .hasArg(true) - .withArgName("RESPONSE_QUEUE") - .create('r')); - - if(hasLinkNameOption()) - { - options.addOption(OptionBuilder.withLongOpt("link") - .withDescription( "link name" ) - .hasArg(true) - .withArgName("LINK") - .create('l')); - } - - if(hasWindowSizeOption()) - { - options.addOption(OptionBuilder.withLongOpt("window-size") - .withDescription("credit window size") - .hasArg(true) - .withArgName("WINDOW-SIZE") - .create('W')); - } - - CommandLine cmdLine = null; - try - { - cmdLine = cmdLineParse.parse(options, args); - - } - catch (ParseException e) - { - printUsage(options); - System.exit(-1); - } - - if(cmdLine.hasOption('h') || cmdLine.getArgList().isEmpty()) - { - printUsage(options); - System.exit(0); - } - _host = cmdLine.getOptionValue('H',"0.0.0.0"); - _remoteHost = cmdLine.getOptionValue('O',null); - String portStr = cmdLine.getOptionValue('p',"5672"); - String countStr = cmdLine.getOptionValue('c',"1"); - - _useSSL = cmdLine.hasOption('S'); - - if(hasWindowSizeOption()) - { - String windowSizeStr = cmdLine.getOptionValue('W',"100"); - _windowSize = Integer.parseInt(windowSizeStr); - } - - if(hasSubjectOption()) - { - _subject = cmdLine.getOptionValue('s'); - } - - if(cmdLine.hasOption('u')) - { - _username = cmdLine.getOptionValue('u'); - } - - if(cmdLine.hasOption('w')) - { - _password = cmdLine.getOptionValue('w'); - } - - if(cmdLine.hasOption('F')) - { - _filter = cmdLine.getOptionValue('F'); - } - - _port = Integer.parseInt(portStr); - - _containerName = cmdLine.getOptionValue('C'); - - if(hasBlockOption()) - _block = cmdLine.hasOption('b'); - - if(hasLinkNameOption()) - _linkName = cmdLine.getOptionValue('l'); - - - if(hasLinkDurableOption()) - _durableLink = cmdLine.hasOption('d'); - - if(hasCountOption()) - _count = Integer.parseInt(countStr); - - if(hasStdInOption()) - _useStdIn = cmdLine.hasOption('i'); - - if(hasSingleLinkPerConnectionMode()) - _useMultipleConnections = cmdLine.hasOption('Z'); - - if(hasTxnOption()) - { - _useTran = cmdLine.hasOption('x'); - _batchSize = Integer.parseInt(cmdLine.getOptionValue('B',"1")); - _rollbackRatio = Double.parseDouble(cmdLine.getOptionValue('R',"0")); - } - - if(hasModeOption()) - { - _mode = AcknowledgeMode.ALO; - - if(cmdLine.hasOption('k')) - { - _mode = AcknowledgeMode.valueOf(cmdLine.getOptionValue('k')); - } - } - - if(hasResponseQueueOption()) - { - _responseQueue = cmdLine.getOptionValue('r'); - } - - _frameSize = Integer.parseInt(cmdLine.getOptionValue('f',"65536")); - - if(hasSizeOption()) - { - _messageSize = Integer.parseInt(cmdLine.getOptionValue('z',"-1")); - } - - String categoriesList = cmdLine.getOptionValue('t'); - String[]categories = categoriesList == null ? new String[0] : categoriesList.split("[, ]"); - for(String cat : categories) - { - if(cat.equalsIgnoreCase("FRM")) - { - FRAME_LOGGER.setLevel(Level.FINE); - Formatter formatter = new Formatter() - { - @Override - public String format(final LogRecord record) - { - return "[" + record.getMillis() + " FRM]\t" + record.getMessage() + "\n"; - } - }; - for(Handler handler : FRAME_LOGGER.getHandlers()) - { - FRAME_LOGGER.removeHandler(handler); - } - Handler handler = new ConsoleHandler(); - handler.setLevel(Level.FINE); - handler.setFormatter(formatter); - FRAME_LOGGER.addHandler(handler); - } - else if (cat.equalsIgnoreCase("RAW")) - { - RAW_LOGGER.setLevel(Level.FINE); - Formatter formatter = new Formatter() - { - @Override - public String format(final LogRecord record) - { - return "[" + record.getMillis() + " RAW]\t" + record.getMessage() + "\n"; - } - }; - for(Handler handler : RAW_LOGGER.getHandlers()) - { - RAW_LOGGER.removeHandler(handler); - } - Handler handler = new ConsoleHandler(); - handler.setLevel(Level.FINE); - handler.setFormatter(formatter); - RAW_LOGGER.addHandler(handler); - } - } - - - _args = cmdLine.getArgs(); - - } - - protected boolean hasFilterOption() - { - return false; - } - - protected boolean hasSubjectOption() - { - return false; - } - - protected boolean hasWindowSizeOption() - { - return false; - } - - protected boolean hasSingleLinkPerConnectionMode() - { - return false; - } - - protected abstract boolean hasLinkDurableOption(); - - protected abstract boolean hasLinkNameOption(); - - protected abstract boolean hasResponseQueueOption(); - - protected abstract boolean hasSizeOption(); - - protected abstract boolean hasBlockOption(); - - protected abstract boolean hasStdInOption(); - - protected abstract boolean hasTxnOption(); - - protected abstract boolean hasModeOption(); - - protected abstract boolean hasCountOption(); - - public String getHost() - { - return _host; - } - - public String getUsername() - { - return _username; - } - - public String getPassword() - { - return _password; - } - - public int getPort() - { - return _port; - } - - public int getCount() - { - return _count; - } - - public boolean useStdIn() - { - return _useStdIn; - } - - public boolean useTran() - { - return _useTran; - } - - public AcknowledgeMode getMode() - { - return _mode; - } - - public boolean isBlock() - { - return _block; - } - - public String[] getArgs() - { - return _args; - } - - public int getMessageSize() - { - return _messageSize; - } - - public String getResponseQueue() - { - return _responseQueue; - } - - public int getBatchSize() - { - return _batchSize; - } - - public double getRollbackRatio() - { - return _rollbackRatio; - } - - public String getLinkName() - { - return _linkName; - } - - public boolean isDurableLink() - { - return _durableLink; - } - - public boolean isUseMultipleConnections() - { - return _useMultipleConnections; - } - - public void setUseMultipleConnections(boolean useMultipleConnections) - { - _useMultipleConnections = useMultipleConnections; - } - - public String getSubject() - { - return _subject; - } - - public void setSubject(String subject) - { - _subject = subject; - } - - protected abstract void printUsage(final Options options); - - protected abstract void run(); - - - public Connection newConnection() throws Connection.ConnectionException - { - Container container = getContainerName() == null ? new Container() : new Container(getContainerName()); - return getUsername() == null ? new Connection(getHost(), getPort(), null, null, _frameSize, container, - _remoteHost == null ? getHost() : _remoteHost, _useSSL) - : new Connection(getHost(), getPort(), getUsername(), getPassword(), _frameSize, - container, _remoteHost == null ? getHost() : _remoteHost, _useSSL); - } - - public String getContainerName() - { - return _containerName; - } - - public int getWindowSize() - { - return _windowSize; - } - - public void setWindowSize(int windowSize) - { - _windowSize = windowSize; - } - - public String getFilter() - { - return _filter; - } -} diff --git a/java/amqp-1-0-common/resources/LICENSE b/java/amqp-1-0-common/resources/LICENSE new file mode 100644 index 0000000000..de4b130f35 --- /dev/null +++ b/java/amqp-1-0-common/resources/LICENSE @@ -0,0 +1,204 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + diff --git a/java/amqp-1-0-common/resources/NOTICE b/java/amqp-1-0-common/resources/NOTICE new file mode 100644 index 0000000000..8d1c3f3122 --- /dev/null +++ b/java/amqp-1-0-common/resources/NOTICE @@ -0,0 +1,5 @@ +Apache Qpid +Copyright 2006-2012 Apache Software Foundation +This product includes software developed at +Apache Software Foundation (http://www.apache.org/) + diff --git a/java/amqp-1-0-common/resources/README.txt b/java/amqp-1-0-common/resources/README.txt new file mode 100644 index 0000000000..35d25050fe --- /dev/null +++ b/java/amqp-1-0-common/resources/README.txt @@ -0,0 +1,7 @@ + +Documentation +-------------- +All of our user documentation can be accessed at: + +http://qpid.apache.org/documentation.html + diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FrameWriter.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FrameWriter.java index dbf9306366..95e327852b 100644 --- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FrameWriter.java +++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/FrameWriter.java @@ -77,13 +77,21 @@ public class FrameWriter implements ValueWriter { case SIZE_0: - _typeWriter.setValue(_frame.getFrameBody()); - int payloadLength = _payload == null ? 0 : _payload.remaining(); - _size = _typeWriter.writeToBuffer(remaining > 8 - ? (ByteBuffer)buffer.duplicate().position(buffer.position()+8) - : ByteBuffer.wrap(EMPTY_BYTE_ARRAY)) + 8 + payloadLength; + if(_typeWriter!=null) + { + _typeWriter.setValue(_frame.getFrameBody()); + + + _size = _typeWriter.writeToBuffer(remaining > 8 + ? (ByteBuffer)buffer.duplicate().position(buffer.position()+8) + : ByteBuffer.wrap(EMPTY_BYTE_ARRAY)) + 8 + payloadLength; + } + else + { + _size = 8 + payloadLength; + } if(remaining >= 4) { buffer.putInt(_size); @@ -239,7 +247,14 @@ public class FrameWriter implements ValueWriter _size = -1; _payload = null; final Object frameBody = frame.getFrameBody(); - _typeWriter = _registry.getValueWriter(frameBody); + if(frameBody!=null) + { + _typeWriter = _registry.getValueWriter(frameBody); + } + else + { + _typeWriter = null; + } _payload = frame.getPayload() == null ? null : frame.getPayload().duplicate(); } } diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/AMQFrame.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/AMQFrame.java index 769fe13d29..9684e290f4 100644 --- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/AMQFrame.java +++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/AMQFrame.java @@ -21,6 +21,7 @@ package org.apache.qpid.amqp_1_0.framing; +import org.apache.qpid.amqp_1_0.type.Binary; import org.apache.qpid.amqp_1_0.type.FrameBody; import java.nio.ByteBuffer; @@ -65,4 +66,11 @@ public abstract class AMQFrame return _frameBody; } + @Override + public String toString() + { + return "AMQFrame{" + + "frameBody=" + _frameBody + + '}'; + } } diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ConnectionHandler.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ConnectionHandler.java index 78bed8a71e..f4cd06f3ef 100644 --- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ConnectionHandler.java +++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ConnectionHandler.java @@ -103,6 +103,7 @@ public class ConnectionHandler private boolean _setForClose; private boolean _closed; + private long _nextHeartbeat; public FrameOutput(final ConnectionEndpoint conn) { @@ -165,14 +166,34 @@ public class ConnectionHandler { synchronized(_conn.getLock()) { + long time = System.currentTimeMillis(); try { AMQFrame frame = null; while(!closed() && (frame = _queue.poll()) == null && wait) { - _conn.getLock().wait(); + _conn.getLock().wait(_conn.getIdleTimeout()/2); + + if(_conn.getIdleTimeout()>0) + { + time = System.currentTimeMillis(); + + if(frame == null && time > _nextHeartbeat) + { + frame = new TransportFrame((short) 0,null); + break; + } + } } + + + + if(frame != null) + { + _nextHeartbeat = time + _conn.getIdleTimeout()/2; + + } if(frame == _endOfFrameMarker) { _closed = true; diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java index 70e990d92e..17bc2caf5f 100644 --- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java +++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java @@ -81,6 +81,8 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour private boolean _closedForInput; private boolean _closedForOutput; + private long _idleTimeout; + private AMQPDescribedTypeRegistry _describedTypeRegistry = AMQPDescribedTypeRegistry.newInstance() .registerTransportLayer() .registerMessagingLayer() @@ -282,6 +284,11 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour _remoteContainerId = open.getContainerId(); + if(open.getIdleTimeOut() != null) + { + _idleTimeout = open.getIdleTimeOut().longValue(); + } + switch(_state) { case UNOPENED: @@ -316,6 +323,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour sendClose(new Close()); break; case CLOSE_SENT: + default: } } @@ -650,6 +658,11 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour return this; } + public synchronized long getIdleTimeout() + { + return _idleTimeout; + } + public synchronized void close() { switch(_state) diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Delivery.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Delivery.java index 4135199045..aca781afb9 100644 --- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Delivery.java +++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Delivery.java @@ -71,6 +71,10 @@ public class Delivery { setComplete(true); } + if(Boolean.TRUE.equals(transfer.getSettled())) + { + setSettled(true); + } } public List getTransfers() diff --git a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java index cf86fc2471..5fbca0b695 100644 --- a/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java +++ b/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ReceivingLinkEndpoint.java @@ -113,33 +113,37 @@ public class ReceivingLinkEndpoint extends LinkEndpoint synchronized (getLock()) { TransientState transientState; - boolean existingState = _unsettledMap.containsKey(transfer.getDeliveryTag()); - _unsettledMap.put(transfer.getDeliveryTag(), transfer.getState()); + final Binary deliveryTag = delivery.getDeliveryTag(); + boolean existingState = _unsettledMap.containsKey(deliveryTag); + if(!existingState || transfer.getState() != null) + { + _unsettledMap.put(deliveryTag, transfer.getState()); + } if(!existingState) { transientState = new TransientState(transfer.getDeliveryId()); - if(Boolean.TRUE.equals(transfer.getSettled())) + if(delivery.isSettled()) { transientState.setSettled(true); } - _unsettledIds.put(transfer.getDeliveryTag(), transientState); + _unsettledIds.put(deliveryTag, transientState); setLinkCredit(getLinkCredit().subtract(UnsignedInteger.ONE)); setDeliveryCount(getDeliveryCount().add(UnsignedInteger.ONE)); } else { - transientState = _unsettledIds.get(transfer.getDeliveryTag()); + transientState = _unsettledIds.get(deliveryTag); transientState.incrementCredit(); - if(Boolean.TRUE.equals(transfer.getSettled())) + if(delivery.isSettled()) { transientState.setSettled(true); } } - if(transientState.isSettled()) + if(transientState.isSettled() && delivery.isComplete()) { - _unsettledMap.remove(transfer.getDeliveryTag()); + _unsettledMap.remove(deliveryTag); } getLinkEventListener().messageTransfer(transfer); @@ -155,7 +159,7 @@ public class ReceivingLinkEndpoint extends LinkEndpoint super.receiveFlow(flow); _remoteDrain = Boolean.TRUE.equals((Boolean)flow.getDrain()); setAvailable(flow.getAvailable()); - _remoteTransferCount = flow.getDeliveryCount(); + setDeliveryCount(flow.getDeliveryCount()); getLock().notifyAll(); } } @@ -371,7 +375,7 @@ public class ReceivingLinkEndpoint extends LinkEndpoint tag = iter.next(); tagsToUpdate.add(tag); - deliveryId = _unsettledIds.get(firstTag).getDeliveryId(); + deliveryId = _unsettledIds.get(tag).getDeliveryId(); if(deliveryId.equals(last.add(UnsignedInteger.ONE))) { diff --git a/java/bdbstore/bin/backup.sh b/java/bdbstore/bin/backup.sh index 61311cd2ef..ba51758d3c 100755 --- a/java/bdbstore/bin/backup.sh +++ b/java/bdbstore/bin/backup.sh @@ -34,11 +34,8 @@ if [ -z "${QPID_HOME}" ]; then export QPID_HOME=`cd ${WHEREAMI}/../ && pwd` fi -VERSION=0.19 - # BDB's je JAR expected to be found in lib/opt -LIBS="${QPID_HOME}/lib/opt/*:${QPID_HOME}/lib/qpid-bdbstore-${VERSION}.jar:${QPID_HOME}/lib/qpid-all.jar" - +LIBS="${QPID_HOME}/lib/opt/*:${QPID_HOME}/lib/qpid-all.jar" echo "Starting Hot Backup Script" java -Dlog4j.configuration=backup-log4j.xml ${JAVA_OPTS} -cp "${LIBS}" org.apache.qpid.server.store.berkeleydb.BDBBackup "${ARGS[@]}" diff --git a/java/bdbstore/build.xml b/java/bdbstore/build.xml index 7c305c7c2f..46809f6a90 100644 --- a/java/bdbstore/build.xml +++ b/java/bdbstore/build.xml @@ -18,7 +18,7 @@ --> - + @@ -78,19 +78,4 @@ http://www.oracle.com/technetwork/database/berkeleydb/downloads/jeoslicense-0868 - - - - - - - - - - - - - - - diff --git a/java/bdbstore/jmx/MANIFEST.MF b/java/bdbstore/jmx/MANIFEST.MF deleted file mode 100644 index ee59bc3ad8..0000000000 --- a/java/bdbstore/jmx/MANIFEST.MF +++ /dev/null @@ -1,20 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Qpid Bdbstore-Plugins JMX -Bundle-SymbolicName: bdbstore-plugins-jmx -Bundle-Description: Bdbstore Management plugin for Qpid. -Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt -Bundle-DocURL: http://www.apache.org/ -Bundle-Version: 1.0.0 -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ClassPath: . -Fragment-Host: broker-plugins-management-jmx -Import-Package: org.apache.qpid, - org.apache.qpid.management.common.mbeans.annotations, - org.apache.qpid.server.model, - org.apache.qpid.server.virtualhost, - org.apache.qpid.server.store.berkeleydb, - org.apache.log4j;version=1.2.16, - javax.management, - javax.management.openmbean -Export-Package: org.apache.qpid.server.store.berkeleydb.jmx diff --git a/java/bdbstore/jmx/build.xml b/java/bdbstore/jmx/build.xml index 229631555d..d3e9f63b46 100644 --- a/java/bdbstore/jmx/build.xml +++ b/java/bdbstore/jmx/build.xml @@ -18,13 +18,13 @@ --> - + - - + + diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java index cfcea602b4..28528ec83c 100644 --- a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java +++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import javax.management.JMException; +import javax.management.ObjectName; import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeType; @@ -91,7 +92,7 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M @Override public String getObjectInstanceName() { - return _store.getName(); + return ObjectName.quote(_store.getName()); } @Override diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java index 837da1eef3..14cdec1669 100644 --- a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java +++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java @@ -28,13 +28,11 @@ import org.apache.qpid.server.jmx.MBeanProvider; import org.apache.qpid.server.jmx.ManagedObject; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; /** * This provide will create a {@link BDBHAMessageStoreManagerMBean} if the child is a virtual - * host and of type {@link BDBHAMessageStore#BDB_HA_STORE_TYPE}. + * host and of type {@link BDBHAMessageStore#TYPE}. * */ public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider @@ -50,7 +48,7 @@ public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider public boolean isChildManageableByMBean(ConfiguredObject child) { return (child instanceof VirtualHost - && BDBHAMessageStore.BDB_HA_STORE_TYPE.equals(child.getAttribute(VirtualHost.STORE_TYPE))); + && BDBHAMessageStore.TYPE.equals(child.getAttribute(VirtualHost.STORE_TYPE))); } @Override @@ -58,10 +56,7 @@ public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider { VirtualHost virtualHostChild = (VirtualHost) child; - VirtualHostRegistry virtualHostRegistry = ApplicationRegistry.getInstance().getVirtualHostRegistry(); - org.apache.qpid.server.virtualhost.VirtualHost vhost = virtualHostRegistry.getVirtualHost(virtualHostChild.getName()); - - BDBHAMessageStore messageStore = (BDBHAMessageStore) vhost.getMessageStore(); + BDBHAMessageStore messageStore = (BDBHAMessageStore) virtualHostChild.getMessageStore(); if (LOGGER.isDebugEnabled()) { diff --git a/java/bdbstore/jmx/src/main/resources/META-INF/services/org.apache.qpid.server.jmx.MBeanProvider b/java/bdbstore/jmx/src/main/resources/META-INF/services/org.apache.qpid.server.jmx.MBeanProvider index b5bc947612..8ece9627b0 100644 --- a/java/bdbstore/jmx/src/main/resources/META-INF/services/org.apache.qpid.server.jmx.MBeanProvider +++ b/java/bdbstore/jmx/src/main/resources/META-INF/services/org.apache.qpid.server.jmx.MBeanProvider @@ -1 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# org.apache.qpid.server.store.berkeleydb.jmx.BDBHAMessageStoreManagerMBeanProvider diff --git a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java index 606983cdae..ff47ed958d 100644 --- a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java +++ b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java @@ -30,6 +30,7 @@ import java.util.Iterator; import java.util.Set; import javax.jms.Connection; +import javax.management.ObjectName; import javax.management.openmbean.CompositeData; import javax.management.openmbean.TabularData; @@ -37,7 +38,6 @@ import org.apache.log4j.Logger; import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.management.common.mbeans.ManagedBroker; import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore; -import org.apache.qpid.server.virtualhost.ManagedVirtualHost; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; @@ -55,7 +55,7 @@ public class HAClusterManagementTest extends QpidBrokerTestCase private static final Set NON_MASTER_STATES = new HashSet(Arrays.asList(REPLICA.toString(), DETACHED.toString(), UNKNOWN.toString()));; private static final String VIRTUAL_HOST = "test"; - private static final String MANAGED_OBJECT_QUERY = "org.apache.qpid:type=BDBHAMessageStore,name=" + VIRTUAL_HOST; + private static final String MANAGED_OBJECT_QUERY = "org.apache.qpid:type=BDBHAMessageStore,name=" + ObjectName.quote(VIRTUAL_HOST); private static final int NUMBER_OF_NODES = 4; private final HATestClusterCreator _clusterCreator = new HATestClusterCreator(this, VIRTUAL_HOST, NUMBER_OF_NODES); @@ -67,7 +67,6 @@ public class HAClusterManagementTest extends QpidBrokerTestCase protected void setUp() throws Exception { _brokerType = BrokerType.SPAWNED; - _jmxUtils.setUp(); _clusterCreator.configureClusterNodes(); _brokerFailoverUrl = _clusterCreator.getConnectionUrlForAllClusterNodes(); @@ -132,12 +131,11 @@ public class HAClusterManagementTest extends QpidBrokerTestCase final int brokerPortNumber = getBrokerPortNumbers().iterator().next(); ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(brokerPortNumber); + awaitAllNodesJoiningGroup(storeBean, NUMBER_OF_NODES); + final TabularData groupMembers = storeBean.getAllNodesInGroup(); assertNotNull(groupMembers); - final int numberOfDataRows = groupMembers.size(); - assertEquals("Unexpected number of data rows", NUMBER_OF_NODES ,numberOfDataRows); - for(int bdbPortNumber : _clusterCreator.getBdbPortNumbers()) { final String nodeName = _clusterCreator.getNodeNameForNodeAt(bdbPortNumber); @@ -155,8 +153,7 @@ public class HAClusterManagementTest extends QpidBrokerTestCase final int brokerPortNumberToMakeObservation = brokerPortNumberIterator.next(); final int brokerPortNumberToBeRemoved = brokerPortNumberIterator.next(); final ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(brokerPortNumberToMakeObservation); - final int numberOfDataRows = storeBean.getAllNodesInGroup().size(); - assertEquals("Unexpected number of data rows before test", NUMBER_OF_NODES ,numberOfDataRows); + awaitAllNodesJoiningGroup(storeBean, NUMBER_OF_NODES); final String removedNodeName = _clusterCreator.getNodeNameForNodeAt(_clusterCreator.getBdbPortForBrokerPort(brokerPortNumberToBeRemoved)); _clusterCreator.stopNode(brokerPortNumberToBeRemoved); @@ -266,4 +263,27 @@ public class HAClusterManagementTest extends QpidBrokerTestCase return _jmxUtils.getManagedBroker(VIRTUAL_HOST); } + + private void awaitAllNodesJoiningGroup(ManagedBDBHAMessageStore storeBean, int expectedNumberOfNodes) throws Exception + { + long totalTimeWaited = 0l; + long waitInterval = 100l; + long maxWaitTime = 10000; + + int currentNumberOfNodes = storeBean.getAllNodesInGroup().size(); + while (expectedNumberOfNodes > currentNumberOfNodes || totalTimeWaited > maxWaitTime) + { + LOGGER.debug("Still awaiting nodes to join group; expecting " + + expectedNumberOfNodes + " node(s) but only have " + currentNumberOfNodes + + " after " + totalTimeWaited + " ms."); + + totalTimeWaited += waitInterval; + Thread.sleep(waitInterval); + + currentNumberOfNodes = storeBean.getAllNodesInGroup().size(); + } + + assertEquals("Unexpected number of nodes in group after " + totalTimeWaited + " ms", + expectedNumberOfNodes ,currentNumberOfNodes); + } } diff --git a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java index 22877ec36c..95626f7fa5 100644 --- a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java +++ b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java @@ -27,6 +27,7 @@ import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.Session; +import javax.management.ObjectName; import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.server.store.berkeleydb.jmx.ManagedBDBHAMessageStore; @@ -41,7 +42,7 @@ public class HAClusterTwoNodeTest extends QpidBrokerTestCase private static final String VIRTUAL_HOST = "test"; - private static final String MANAGED_OBJECT_QUERY = "org.apache.qpid:type=BDBHAMessageStore,name=" + VIRTUAL_HOST; + private static final String MANAGED_OBJECT_QUERY = "org.apache.qpid:type=BDBHAMessageStore,name=" + ObjectName.quote(VIRTUAL_HOST); private static final int NUMBER_OF_NODES = 2; private final HATestClusterCreator _clusterCreator = new HATestClusterCreator(this, VIRTUAL_HOST, NUMBER_OF_NODES); @@ -56,7 +57,6 @@ public class HAClusterTwoNodeTest extends QpidBrokerTestCase assertTrue(isJavaBroker()); assertTrue(isBrokerStorePersistent()); - _jmxUtils.setUp(); super.setUp(); } @@ -86,11 +86,11 @@ public class HAClusterTwoNodeTest extends QpidBrokerTestCase String storeConfigKeyPrefix = _clusterCreator.getStoreConfigKeyPrefix(); - setConfigurationProperty(storeConfigKeyPrefix + ".repConfig(0).name", ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT); - setConfigurationProperty(storeConfigKeyPrefix + ".repConfig(0).value", "2 s"); + setVirtualHostConfigurationProperty(storeConfigKeyPrefix + ".repConfig(0).name", ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT); + setVirtualHostConfigurationProperty(storeConfigKeyPrefix + ".repConfig(0).value", "2 s"); - setConfigurationProperty(storeConfigKeyPrefix + ".repConfig(1).name", ReplicationConfig.ELECTIONS_PRIMARY_RETRIES); - setConfigurationProperty(storeConfigKeyPrefix + ".repConfig(1).value", "0"); + setVirtualHostConfigurationProperty(storeConfigKeyPrefix + ".repConfig(1).name", ReplicationConfig.ELECTIONS_PRIMARY_RETRIES); + setVirtualHostConfigurationProperty(storeConfigKeyPrefix + ".repConfig(1).value", "0"); _clusterCreator.configureClusterNodes(); _clusterCreator.setDesignatedPrimaryOnFirstBroker(designedPrimary); diff --git a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java index 49b3ddd3dc..298d5bc045 100644 --- a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java +++ b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import javax.management.JMException; +import javax.management.ObjectName; import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeType; import javax.management.openmbean.TabularData; @@ -84,7 +85,7 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase { when(_store.getName()).thenReturn(TEST_STORE_NAME); - String expectedObjectName = "org.apache.qpid:type=BDBHAMessageStore,name=" + TEST_STORE_NAME; + String expectedObjectName = "org.apache.qpid:type=BDBHAMessageStore,name=" + ObjectName.quote(TEST_STORE_NAME); assertEquals(expectedObjectName, _mBean.getObjectName().toString()); } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java index 9323111fdd..6e64ea5597 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java @@ -54,13 +54,10 @@ import org.apache.qpid.AMQStoreException; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.federation.Bridge; -import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.store.*; import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BindingRecoveryHandler; -import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler; import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecoveryHandler; import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler; import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler; @@ -73,7 +70,6 @@ import org.apache.qpid.server.store.berkeleydb.tuple.ContentBinding; import org.apache.qpid.server.store.berkeleydb.tuple.MessageMetaDataBinding; import org.apache.qpid.server.store.berkeleydb.tuple.PreparedTransactionBinding; import org.apache.qpid.server.store.berkeleydb.tuple.QueueEntryBinding; -import org.apache.qpid.server.store.berkeleydb.tuple.StringMapBinding; import org.apache.qpid.server.store.berkeleydb.tuple.UUIDTupleBinding; import org.apache.qpid.server.store.berkeleydb.tuple.XidBinding; import org.apache.qpid.server.store.berkeleydb.upgrade.Upgrader; @@ -423,8 +419,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore BindingRecoveryHandler brh = qrh.completeQueueRecovery(); _configuredObjectHelper.recoverBindings(brh, configuredObjects); - BrokerLinkRecoveryHandler lrh = brh.completeBindingRecovery(); - recoverBrokerLinks(lrh); + brh.completeBindingRecovery(); } catch (DatabaseException e) { @@ -466,66 +461,6 @@ public abstract class AbstractBDBMessageStore implements MessageStore } } - private void recoverBrokerLinks(final ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler lrh) - { - Cursor cursor = null; - - try - { - cursor = _linkDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - UUID id = UUIDTupleBinding.getInstance().entryToObject(key); - long createTime = LongBinding.entryToLong(value); - Map arguments = StringMapBinding.getInstance().entryToObject(value); - - ConfigurationRecoveryHandler.BridgeRecoveryHandler brh = lrh.brokerLink(id, createTime, arguments); - - recoverBridges(brh, id); - } - } - finally - { - closeCursorSafely(cursor); - } - - } - - private void recoverBridges(final ConfigurationRecoveryHandler.BridgeRecoveryHandler brh, final UUID linkId) - { - Cursor cursor = null; - - try - { - cursor = _bridgeDb.openCursor(null, null); - DatabaseEntry key = new DatabaseEntry(); - DatabaseEntry value = new DatabaseEntry(); - - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) - { - UUID id = UUIDTupleBinding.getInstance().entryToObject(key); - - UUID parentId = UUIDTupleBinding.getInstance().entryToObject(value); - if(parentId.equals(linkId)) - { - - long createTime = LongBinding.entryToLong(value); - Map arguments = StringMapBinding.getInstance().entryToObject(value); - brh.bridge(id,createTime,arguments); - } - } - brh.completeBridgeRecoveryForLink(); - } - finally - { - closeCursorSafely(cursor); - } - - } - private void recoverMessages(MessageStoreRecoveryHandler msrh) throws DatabaseException { @@ -940,89 +875,6 @@ public abstract class AbstractBDBMessageStore implements MessageStore } } - public void createBrokerLink(final BrokerLink link) throws AMQStoreException - { - if (_stateManager.isInState(State.ACTIVE)) - { - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding.getInstance().objectToEntry(link.getQMFId(), key); - - DatabaseEntry value = new DatabaseEntry(); - LongBinding.longToEntry(link.getCreateTime(), value); - StringMapBinding.getInstance().objectToEntry(link.getArguments(), value); - - try - { - _linkDb.put(null, key, value); - } - catch (DatabaseException e) - { - throw new AMQStoreException("Error writing Link " + link - + " to database: " + e.getMessage(), e); - } - } - } - - public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException - { - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding.getInstance().objectToEntry(link.getQMFId(), key); - try - { - OperationStatus status = _linkDb.delete(null, key); - if (status == OperationStatus.NOTFOUND) - { - throw new AMQStoreException("Link " + link + " not found"); - } - } - catch (DatabaseException e) - { - throw new AMQStoreException("Error deleting the Link " + link + " from database: " + e.getMessage(), e); - } - } - - public void createBridge(final Bridge bridge) throws AMQStoreException - { - if (_stateManager.isInState(State.ACTIVE)) - { - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding.getInstance().objectToEntry(bridge.getQMFId(), key); - - DatabaseEntry value = new DatabaseEntry(); - UUIDTupleBinding.getInstance().objectToEntry(bridge.getLink().getQMFId(),value); - LongBinding.longToEntry(bridge.getCreateTime(),value); - StringMapBinding.getInstance().objectToEntry(bridge.getArguments(), value); - - try - { - _bridgeDb.put(null, key, value); - } - catch (DatabaseException e) - { - throw new AMQStoreException("Error writing Bridge " + bridge - + " to database: " + e.getMessage(), e); - } - - } - } - - public void deleteBridge(final Bridge bridge) throws AMQStoreException - { - DatabaseEntry key = new DatabaseEntry(); - UUIDTupleBinding.getInstance().objectToEntry(bridge.getQMFId(), key); - try - { - OperationStatus status = _bridgeDb.delete(null, key); - if (status == OperationStatus.NOTFOUND) - { - throw new AMQStoreException("Bridge " + bridge + " not found"); - } - } - catch (DatabaseException e) - { - throw new AMQStoreException("Error deleting the Bridge " + bridge + " from database: " + e.getMessage(), e); - } - } /** * Places a message onto a specified queue, in a given transaction. @@ -1050,7 +902,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore { LOGGER.debug("Enqueuing message " + messageId + " on queue " + (queue instanceof AMQQueue ? ((AMQQueue) queue).getName() + " with id " : "") + queue.getId() - + " [Transaction" + tx + "]"); + + " in transaction " + tx); } _deliveryDb.put(tx, key, value); } @@ -1204,7 +1056,8 @@ public abstract class AbstractBDBMessageStore implements MessageStore if (LOGGER.isDebugEnabled()) { - LOGGER.debug("commitTranImpl completed for [Transaction:" + tx + "]"); + String transactionType = syncCommit ? "synchronous" : "asynchronous"; + LOGGER.debug("commitTranImpl completed " + transactionType + " transaction " + tx); } } catch (DatabaseException e) @@ -1226,7 +1079,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("abortTran called for [Transaction:" + tx + "]"); + LOGGER.debug("abortTran called for transaction " + tx); } try @@ -1338,7 +1191,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Storing content for message " + messageId + "[Transaction" + tx + "]"); + LOGGER.debug("Storing content for message " + messageId + " in transaction " + tx); } } @@ -1363,8 +1216,9 @@ public abstract class AbstractBDBMessageStore implements MessageStore { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("public void storeMetaData(Txn tx = " + tx + ", Long messageId = " - + messageId + ", MessageMetaData messageMetaData = " + messageMetaData + "): called"); + LOGGER.debug("storeMetaData called for transaction " + tx + + ", messageId " + messageId + + ", messageMetaData " + messageMetaData); } DatabaseEntry key = new DatabaseEntry(); @@ -1378,7 +1232,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore _messageMetaDataDb.put(tx, key, value); if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Storing message metadata for message id " + messageId + "[Transaction" + tx + "]"); + LOGGER.debug("Storing message metadata for message id " + messageId + " in transaction " + tx); } } catch (DatabaseException e) @@ -1680,7 +1534,8 @@ public abstract class AbstractBDBMessageStore implements MessageStore else { ByteBuffer buf = ByteBuffer.allocate(size); - getContent(offsetInMessage, buf); + int length = getContent(offsetInMessage, buf); + buf.limit(length); buf.position(0); return buf; } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java index c40f24dbc3..ba111e8091 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java @@ -105,7 +105,7 @@ public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMess put(ReplicationConfig.LOG_FLUSH_TASK_INTERVAL, "1 min"); }}); - public static final String BDB_HA_STORE_TYPE = "BDB-HA"; + public static final String TYPE = "BDB-HA"; private String _groupName; private String _nodeName; @@ -602,6 +602,6 @@ public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMess @Override public String getStoreType() { - return BDB_HA_STORE_TYPE; + return TYPE; } } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreFactory.java new file mode 100644 index 0000000000..20dce2628d --- /dev/null +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreFactory.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store.berkeleydb; + +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.MessageStoreFactory; + +public class BDBHAMessageStoreFactory implements MessageStoreFactory +{ + + @Override + public String getType() + { + return BDBHAMessageStore.TYPE; + } + + @Override + public MessageStore createMessageStore() + { + return new BDBHAMessageStore(); + } + +} diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java index 82bc3d8564..4028de4b80 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java @@ -42,7 +42,7 @@ import com.sleepycat.je.EnvironmentConfig; public class BDBMessageStore extends AbstractBDBMessageStore { private static final Logger LOGGER = Logger.getLogger(BDBMessageStore.class); - private static final String BDB_STORE_TYPE = "BDB"; + public static final String TYPE = "BDB"; private CommitThreadWrapper _commitThreadWrapper; @Override @@ -108,7 +108,7 @@ public class BDBMessageStore extends AbstractBDBMessageStore @Override public String getStoreType() { - return BDB_STORE_TYPE; + return TYPE; } } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java new file mode 100644 index 0000000000..126bf1928a --- /dev/null +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store.berkeleydb; + +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.MessageStoreFactory; + +public class BDBMessageStoreFactory implements MessageStoreFactory +{ + + @Override + public String getType() + { + return BDBMessageStore.TYPE; + } + + @Override + public MessageStore createMessageStore() + { + return new BDBMessageStore(); + } + +} diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java index fe1556b5a6..598d20146c 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/CommitThreadWrapper.java @@ -80,7 +80,7 @@ public class CommitThreadWrapper { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("public synchronized void complete(): called (Transaction = " + _tx + ")"); + LOGGER.debug("complete() called for transaction " + _tx); } _complete = true; @@ -101,7 +101,10 @@ public class CommitThreadWrapper if(!_syncCommit) { - LOGGER.debug("CommitAsync was requested, returning immediately."); + if(LOGGER.isDebugEnabled()) + { + LOGGER.debug("CommitAsync was requested, returning immediately."); + } return; } @@ -121,6 +124,12 @@ public class CommitThreadWrapper public synchronized void waitForCompletion() { + long startTime = 0; + if(LOGGER.isDebugEnabled()) + { + startTime = System.currentTimeMillis(); + } + while (!isComplete()) { _commitThread.explicitNotify(); @@ -133,6 +142,12 @@ public class CommitThreadWrapper throw new RuntimeException(e); } } + + if(LOGGER.isDebugEnabled()) + { + long duration = System.currentTimeMillis() - startTime; + LOGGER.debug("waitForCompletion returning after " + duration + " ms for transaction " + _tx); + } } } @@ -198,8 +213,20 @@ public class CommitThreadWrapper try { + long startTime = 0; + if(LOGGER.isDebugEnabled()) + { + startTime = System.currentTimeMillis(); + } + _environment.flushLog(true); + if(LOGGER.isDebugEnabled()) + { + long duration = System.currentTimeMillis() - startTime; + LOGGER.debug("flushLog completed in " + duration + " ms"); + } + for(int i = 0; i < size; i++) { BDBCommitFuture commit = _jobQueue.poll(); diff --git a/java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.store.MessageStoreFactory b/java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.store.MessageStoreFactory new file mode 100644 index 0000000000..0be7035e2e --- /dev/null +++ b/java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.store.MessageStoreFactory @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory +org.apache.qpid.server.store.berkeleydb.BDBHAMessageStoreFactory \ No newline at end of file diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java index 342c185b99..7c04d83e79 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java @@ -63,7 +63,7 @@ public class BDBBackupTest extends QpidBrokerTestCase // It would be preferable to lookup the store path using #getConfigurationStringProperty("virtualhosts...") // but the config as known to QBTC does not pull-in the virtualhost section from its separate source file - _backupFromDir = new File(qpidWork + "/bdbstore/" + TEST_VHOST + "-store"); + _backupFromDir = new File(qpidWork + File.separator + TEST_VHOST + "-store"); boolean fromDirExistsAndIsDir = _backupFromDir.isDirectory(); assertTrue("backupFromDir " + _backupFromDir + " should already exist", fromDirExistsAndIsDir); } diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java index a04fb20680..8e32a1d113 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java @@ -24,12 +24,8 @@ import java.io.File; import java.net.InetAddress; import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.logging.SystemOutMessageLogger; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.TestLogActor; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.TestApplicationRegistry; +import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.util.FileUtils; @@ -51,6 +47,7 @@ public class BDBHAMessageStoreTest extends QpidTestCase private int _masterPort; private String _host; private XMLConfiguration _configXml; + private VirtualHost _virtualHost; public void setUp() throws Exception { @@ -63,41 +60,48 @@ public class BDBHAMessageStoreTest extends QpidTestCase FileUtils.delete(new File(_workDir), true); _configXml = new XMLConfiguration(); - } - public void tearDown() throws Exception - { - FileUtils.delete(new File(_workDir), true); - super.tearDown(); - } + BrokerTestHelper.setUp(); + } - public void testSetSystemConfiguration() throws Exception + public void tearDown() throws Exception { - // create virtual host configuration, registry and host instance - addVirtualHostConfiguration(); - TestApplicationRegistry registry = initialize(); try { - VirtualHost virtualhost = registry.getVirtualHostRegistry().getVirtualHost("test" + _masterPort); - BDBHAMessageStore store = (BDBHAMessageStore) virtualhost.getMessageStore(); - - // test whether JVM system settings were applied - Environment env = store.getEnvironment(); - assertEquals("Unexpected number of cleaner threads", TEST_NUMBER_OF_THREADS, env.getConfig().getConfigParam(EnvironmentConfig.CLEANER_THREADS)); - assertEquals("Unexpected log file max", TEST_LOG_FILE_MAX, env.getConfig().getConfigParam(EnvironmentConfig.LOG_FILE_MAX)); - - ReplicatedEnvironment repEnv = store.getReplicatedEnvironment(); - assertEquals("Unexpected number of elections primary retries", TEST_ELECTION_RETRIES, - repEnv.getConfig().getConfigParam(ReplicationConfig.ELECTIONS_PRIMARY_RETRIES)); - assertEquals("Unexpected number of elections primary retries", TEST_ENV_CONSISTENCY_TIMEOUT, - repEnv.getConfig().getConfigParam(ReplicationConfig.ENV_CONSISTENCY_TIMEOUT)); + FileUtils.delete(new File(_workDir), true); + if (_virtualHost != null) + { + _virtualHost.close(); + } } finally { - ApplicationRegistry.remove(); + BrokerTestHelper.tearDown(); + super.tearDown(); } } + public void testSetSystemConfiguration() throws Exception + { + // create virtual host configuration, registry and host instance + addVirtualHostConfiguration(); + String vhostName = "test" + _masterPort; + VirtualHostConfiguration configuration = new VirtualHostConfiguration(vhostName, _configXml.subset("virtualhosts.virtualhost." + vhostName), BrokerTestHelper.createBrokerMock()); + _virtualHost = BrokerTestHelper.createVirtualHost(configuration); + BDBHAMessageStore store = (BDBHAMessageStore) _virtualHost.getMessageStore(); + + // test whether JVM system settings were applied + Environment env = store.getEnvironment(); + assertEquals("Unexpected number of cleaner threads", TEST_NUMBER_OF_THREADS, env.getConfig().getConfigParam(EnvironmentConfig.CLEANER_THREADS)); + assertEquals("Unexpected log file max", TEST_LOG_FILE_MAX, env.getConfig().getConfigParam(EnvironmentConfig.LOG_FILE_MAX)); + + ReplicatedEnvironment repEnv = store.getReplicatedEnvironment(); + assertEquals("Unexpected number of elections primary retries", TEST_ELECTION_RETRIES, + repEnv.getConfig().getConfigParam(ReplicationConfig.ELECTIONS_PRIMARY_RETRIES)); + assertEquals("Unexpected number of elections primary retries", TEST_ENV_CONSISTENCY_TIMEOUT, + repEnv.getConfig().getConfigParam(ReplicationConfig.ENV_CONSISTENCY_TIMEOUT)); + } + private void addVirtualHostConfiguration() throws Exception { int port = findFreePort(); @@ -152,14 +156,4 @@ public class BDBHAMessageStoreTest extends QpidTestCase } return _host + ":" + _masterPort; } - - private TestApplicationRegistry initialize() throws Exception - { - CurrentActor.set(new TestLogActor(new SystemOutMessageLogger())); - ServerConfiguration configuration = new ServerConfiguration(_configXml); - TestApplicationRegistry registry = new TestApplicationRegistry(configuration); - ApplicationRegistry.initialise(registry); - registry.getVirtualHostRegistry().setDefaultVirtualHostName("test" + _masterPort); - return registry; - } } diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java index eef9f7eab4..d18c850ecf 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java @@ -225,7 +225,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto messageStore.close(); AbstractBDBMessageStore newStore = new BDBMessageStore(); - newStore.configure("", _config.subset("store")); + newStore.configure("", getConfig().subset("store")); newStore.startWithNoRecover(); diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java index 122f846a2d..390d667db0 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java @@ -20,6 +20,9 @@ */ package org.apache.qpid.server.store.berkeleydb; +import java.util.HashMap; +import java.util.Map; + import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.Destination; @@ -35,6 +38,11 @@ import javax.jms.TopicConnection; import javax.jms.TopicPublisher; import javax.jms.TopicSession; import javax.jms.TopicSubscriber; +import javax.management.MBeanServerConnection; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; import org.apache.qpid.client.AMQConnectionFactory; import org.apache.qpid.client.AMQDestination; @@ -62,6 +70,11 @@ public class BDBStoreUpgradeTestPreparer public static final String QUEUE_NAME="myUpgradeQueue"; public static final String NON_DURABLE_QUEUE_NAME="queue-non-durable"; + public static final String PRIORITY_QUEUE_NAME="myPriorityQueue"; + public static final String QUEUE_WITH_DLQ_NAME="myQueueWithDLQ"; + public static final String NONEXCLUSIVE_WITH_ERRONEOUS_OWNER = "nonexclusive-with-erroneous-owner"; + public static final String MISUSED_OWNER = "misused-owner-as-description"; + private static AMQConnectionFactory _connFac; private static final String CONN_URL = "amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672'"; @@ -86,10 +99,10 @@ public class BDBStoreUpgradeTestPreparer { Connection connection = _connFac.createConnection(); AMQSession session = (AMQSession)connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - AMQShortString queueName = AMQShortString.valueOf(NON_DURABLE_QUEUE_NAME); + AMQShortString queueName = new AMQShortString(NON_DURABLE_QUEUE_NAME); AMQDestination destination = (AMQDestination) session.createQueue(NON_DURABLE_QUEUE_NAME); session.sendCreateQueue(queueName, false, false, false, null); - session.bindQueue(queueName, queueName, null, AMQShortString.valueOf("amq.direct"), destination); + session.bindQueue(queueName, queueName, null, new AMQShortString("amq.direct"), destination); MessageProducer messageProducer = session.createProducer(destination); sendMessages(session, messageProducer, destination, DeliveryMode.PERSISTENT, 1024, 3); connection.close(); @@ -140,11 +153,56 @@ public class BDBStoreUpgradeTestPreparer // Publish 5 persistent messages which will NOT be committed and so should be 'lost' sendMessages(session, messageProducer, queue, DeliveryMode.PERSISTENT, 1*1024, 5); + messageProducer.close(); + session.close(); + + session = connection.createSession(true, Session.SESSION_TRANSACTED); + // Create a priority queue on broker + final Map priorityQueueArguments = new HashMap(); + priorityQueueArguments.put("x-qpid-priorities",10); + createAndBindQueueOnBroker(session, PRIORITY_QUEUE_NAME, priorityQueueArguments); + + // Create a queue that has a DLQ + final Map queueWithDLQArguments = new HashMap(); + queueWithDLQArguments.put("x-qpid-dlq-enabled", true); + queueWithDLQArguments.put("x-qpid-maximum-delivery-count", 2); + createAndBindQueueOnBroker(session, QUEUE_WITH_DLQ_NAME, queueWithDLQArguments); + + // Send message to the DLQ + Queue dlq = session.createQueue("fanout://" + QUEUE_WITH_DLQ_NAME + "_DLE//does-not-matter"); + MessageProducer dlqMessageProducer = session.createProducer(dlq); + sendMessages(session, dlqMessageProducer, dlq, DeliveryMode.PERSISTENT, 1*1024, 1); + session.commit(); + // Create a queue with JMX specifying an owner, so it can later be moved into description + createAndBindQueueOnBrokerWithJMX(NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, MISUSED_OWNER, priorityQueueArguments); session.close(); connection.close(); } + private void createAndBindQueueOnBroker(Session session, String queueName, final Map arguments) throws Exception + { + ((AMQSession) session).createQueue(new AMQShortString(queueName), false, true, false, arguments); + Queue queue = (Queue) session.createQueue("direct://amq.direct/"+queueName+"/"+queueName+"?durable='true'"); + ((AMQSession) session).declareAndBind((AMQDestination)queue); + } + + private void createAndBindQueueOnBrokerWithJMX(String queueName, String owner, final Map arguments) throws Exception + { + Map environment = new HashMap(); + environment.put(JMXConnector.CREDENTIALS, new String[] {"admin","admin"}); + JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:8999/jmxrmi"); + JMXConnector jmxConnector = JMXConnectorFactory.connect(url, environment); + MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); + ObjectName virtualHost = new ObjectName("org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=\"test\""); + + Object[] params = new Object[] {queueName, owner, true, arguments}; + String[] signature = new String[] {String.class.getName(), String.class.getName(), boolean.class.getName(), Map.class.getName()}; + mbsc.invoke(virtualHost, "createNewQueue", params, signature); + + ObjectName directExchange = new ObjectName("org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=\"test\",name=\"amq.direct\",ExchangeType=direct"); + mbsc.invoke(directExchange, "createNewBinding", new Object[] {queueName, queueName}, new String[] {String.class.getName(), String.class.getName()}); + } /** * Prepare a DurableSubscription backing queue for use in testing selector * recovery and queue exclusivity marking during the upgrade process. diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java index 4e201d5473..e4837b212e 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java @@ -22,16 +22,20 @@ package org.apache.qpid.server.store.berkeleydb; import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.NON_DURABLE_QUEUE_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.PRIORITY_QUEUE_NAME; import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_WITH_DLQ_NAME; import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.SELECTOR_SUB_NAME; import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.SELECTOR_TOPIC_NAME; import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.SUB_NAME; import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.TOPIC_NAME; import java.io.File; +import java.io.InputStream; import javax.jms.Connection; import javax.jms.DeliveryMode; +import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; @@ -43,7 +47,10 @@ import javax.jms.TopicConnection; import javax.jms.TopicPublisher; import javax.jms.TopicSession; import javax.jms.TopicSubscriber; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.TabularDataSupport; +import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.management.common.mbeans.ManagedQueue; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; @@ -70,7 +77,7 @@ public class BDBUpgradeTest extends QpidBrokerTestCase public void setUp() throws Exception { assertNotNull("QPID_WORK must be set", QPID_WORK_ORIG); - _storeLocation = getWorkDirBaseDir() + "/bdbstore/test-store"; + _storeLocation = getWorkDirBaseDir() + File.separator + "test-store"; //Clear the two target directories if they exist. File directory = new File(_storeLocation); @@ -78,15 +85,13 @@ public class BDBUpgradeTest extends QpidBrokerTestCase { FileUtils.delete(directory, true); } + directory.mkdirs(); // copy store files - String src = getClass().getClassLoader().getResource("upgrade/bdbstore-v4/test-store").toURI().getPath(); - FileUtils.copyRecursive(new File(src), new File(_storeLocation)); - - //override the broker config used and then start the broker with the updated store - _configFile = new File("build/etc/config-systests-bdb.xml"); - setConfigurationProperty("management.enabled", "true"); + InputStream src = getClass().getClassLoader().getResourceAsStream("upgrade/bdbstore-v4/test-store/00000000.jdb"); + FileUtils.copy(src, new File(_storeLocation, "00000000.jdb")); + getBrokerConfiguration().addJmxManagementConfiguration(); super.setUp(); } @@ -302,11 +307,110 @@ public class BDBUpgradeTest extends QpidBrokerTestCase Queue queue = session.createQueue(NON_DURABLE_QUEUE_NAME); MessageConsumer messageConsumer = session.createConsumer(queue); - for (int i = 0; i < 3; i++) + for (int i = 1; i <= 3; i++) { Message message = messageConsumer.receive(1000); assertNotNull("Message was not migrated!", message); assertTrue("Unexpected message received!", message instanceof TextMessage); + assertEquals("ID property did not match", i, message.getIntProperty("ID")); + } + } + + /** + * Tests store upgrade has maintained the priority queue configuration, + * such that sending messages with priorities out-of-order and then consuming + * them gets the messages back in priority order. + */ + public void testPriorityQueue() throws Exception + { + // Create a connection and start it + Connection connection = getConnection(); + connection.start(); + + // send some messages to the priority queue + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Queue queue = session.createQueue(PRIORITY_QUEUE_NAME); + MessageProducer producer = session.createProducer(queue); + + producer.setPriority(4); + producer.send(createMessage(1, false, session, producer)); + producer.setPriority(1); + producer.send(createMessage(2, false, session, producer)); + producer.setPriority(9); + producer.send(createMessage(3, false, session, producer)); + session.close(); + + //consume the messages, expected order: msg 3, msg 1, msg 2. + session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + MessageConsumer consumer = session.createConsumer(queue); + + Message msg = consumer.receive(1500); + assertNotNull("expected message was not received", msg); + assertEquals(3, msg.getIntProperty("msg")); + msg = consumer.receive(1500); + assertNotNull("expected message was not received", msg); + assertEquals(1, msg.getIntProperty("msg")); + msg = consumer.receive(1500); + assertNotNull("expected message was not received", msg); + assertEquals(2, msg.getIntProperty("msg")); + } + + /** + * Test that the queue configured to have a DLQ was recovered and has the alternate exchange + * and max delivery count, the DLE exists, the DLQ exists with no max delivery count, the + * DLQ is bound to the DLE, and that the DLQ does not itself have a DLQ. + * + * DLQs are NOT enabled at the virtualhost level, we are testing recovery of the arguments + * that turned it on for this specific queue. + */ + public void testRecoveryOfQueueWithDLQ() throws Exception + { + JMXTestUtils jmxUtils = null; + try + { + jmxUtils = new JMXTestUtils(this, "guest", "guest"); + jmxUtils.open(); + } + catch (Exception e) + { + fail("Unable to establish JMX connection, test cannot proceed"); + } + + try + { + //verify the DLE exchange exists, has the expected type, and a single binding for the DLQ + ManagedExchange exchange = jmxUtils.getManagedExchange(QUEUE_WITH_DLQ_NAME + "_DLE"); + assertEquals("Wrong exchange type", "fanout", exchange.getExchangeType()); + TabularDataSupport bindings = (TabularDataSupport) exchange.bindings(); + assertEquals(1, bindings.size()); + for(Object o : bindings.values()) + { + CompositeData binding = (CompositeData) o; + + String bindingKey = (String) binding.get(ManagedExchange.BINDING_KEY); + String[] queueNames = (String[]) binding.get(ManagedExchange.QUEUE_NAMES); + + //Because its a fanout exchange, we just return a single '*' key with all bound queues + assertEquals("unexpected binding key", "*", bindingKey); + assertEquals("unexpected number of queues bound", 1, queueNames.length); + assertEquals("unexpected queue name", QUEUE_WITH_DLQ_NAME + "_DLQ", queueNames[0]); + } + + //verify the queue exists, has the expected alternate exchange and max delivery count + ManagedQueue queue = jmxUtils.getManagedQueue(QUEUE_WITH_DLQ_NAME); + assertEquals("Queue does not have the expected AlternateExchange", QUEUE_WITH_DLQ_NAME + "_DLE", queue.getAlternateExchange()); + assertEquals("Unexpected maximum delivery count", Integer.valueOf(2), queue.getMaximumDeliveryCount()); + + ManagedQueue dlQqueue = jmxUtils.getManagedQueue(QUEUE_WITH_DLQ_NAME + "_DLQ"); + assertNull("Queue should not have an AlternateExchange", dlQqueue.getAlternateExchange()); + assertEquals("Unexpected maximum delivery count", Integer.valueOf(0), dlQqueue.getMaximumDeliveryCount()); + + String dlqDlqObjectNameString = jmxUtils.getQueueObjectNameString("test", QUEUE_WITH_DLQ_NAME + "_DLQ" + "_DLQ"); + assertFalse("a DLQ should not exist for the DLQ itself", jmxUtils.doesManagedObjectExist(dlqDlqObjectNameString)); + } + finally + { + jmxUtils.close(); } } @@ -387,4 +491,11 @@ public class BDBUpgradeTest extends QpidBrokerTestCase session.close(); } + private Message createMessage(int msgId, boolean first, Session producerSession, MessageProducer producer) throws JMSException + { + Message send = producerSession.createTextMessage("Message: " + msgId); + send.setIntProperty("msg", msgId); + + return send; + } } diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java index c6a9ba8f8b..0e1ef7b25d 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java @@ -31,6 +31,7 @@ import org.apache.qpid.client.AMQConnection; import org.apache.qpid.jms.ConnectionListener; import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestUtils; import com.sleepycat.je.rep.ReplicationConfig; @@ -134,7 +135,10 @@ public class HAClusterBlackboxTest extends QpidBrokerTestCase public void assertFailoverOccurs(long delay) throws InterruptedException { - _failoverLatch.await(delay, TimeUnit.MILLISECONDS); + if (!_failoverLatch.await(delay, TimeUnit.MILLISECONDS)) + { + LOGGER.warn("Test thread dump:\n\n" + TestUtils.dumpThreads() + "\n"); + } assertEquals("Failover did not occur", 0, _failoverLatch.getCount()); } diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java index abe13edc32..4c2fa910f5 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java @@ -43,6 +43,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionURL; +import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.url.URLSyntaxException; @@ -67,7 +68,7 @@ public class HATestClusterCreator private final Map _brokerPortToBdbPortMap = new HashMap(); private final Map _brokerConfigurations = new TreeMap(); private final String _virtualHostName; - private final String _storeConfigKeyPrefix; + private final String _vhostStoreConfigKeyPrefix; private final String _ipAddressOfBroker; private final String _groupName ; @@ -82,7 +83,7 @@ public class HATestClusterCreator _groupName = "group" + _testcase.getName(); _ipAddressOfBroker = getIpAddressOfBrokerHost(); _numberOfNodes = numberOfNodes; - _storeConfigKeyPrefix = "virtualhosts.virtualhost." + _virtualHostName + ".store."; + _vhostStoreConfigKeyPrefix = "virtualhosts.virtualhost." + _virtualHostName + ".store."; _bdbHelperPort = 0; } @@ -102,7 +103,9 @@ public class HATestClusterCreator } configureClusterNode(brokerPort, bdbPort); - collectConfig(brokerPort, _testcase.getTestConfiguration(), _testcase.getTestVirtualhosts()); + TestBrokerConfiguration brokerConfiguration = _testcase.getBrokerConfiguration(brokerPort); + brokerConfiguration.addJmxManagementConfiguration(); + collectConfig(brokerPort, brokerConfiguration, _testcase.getTestVirtualhosts()); brokerPort = _testcase.getNextAvailable(bdbPort + 1); } @@ -127,7 +130,7 @@ public class HATestClusterCreator */ private String getConfigKey(String configKeySuffix) { - final String configKey = StringUtils.substringAfter(_storeConfigKeyPrefix + configKeySuffix, "virtualhosts."); + final String configKey = StringUtils.substringAfter(_vhostStoreConfigKeyPrefix + configKeySuffix, "virtualhosts."); return configKey; } @@ -135,7 +138,6 @@ public class HATestClusterCreator { final BrokerConfigHolder brokerConfigHolder = _brokerConfigurations.get(brokerPortNumber); - _testcase.setTestConfiguration(brokerConfigHolder.getTestConfiguration()); _testcase.setTestVirtualhosts(brokerConfigHolder.getTestVirtualhosts()); _testcase.startBroker(brokerPortNumber); @@ -204,7 +206,7 @@ public class HATestClusterCreator public void stopNode(final int brokerPortNumber) { - _testcase.stopBroker(brokerPortNumber); + _testcase.killBroker(brokerPortNumber); } public void stopCluster() throws Exception @@ -348,12 +350,12 @@ public class HATestClusterCreator { final String nodeName = getNodeNameForNodeAt(bdbPort); - _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "class", "org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore"); + _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "class", "org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore"); - _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "highAvailability.groupName", _groupName); - _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "highAvailability.nodeName", nodeName); - _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "highAvailability.nodeHostPort", getNodeHostPortForNodeAt(bdbPort)); - _testcase.setConfigurationProperty(_storeConfigKeyPrefix + "highAvailability.helperHostPort", getHelperHostPort()); + _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "highAvailability.groupName", _groupName); + _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "highAvailability.nodeName", nodeName); + _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "highAvailability.nodeHostPort", getNodeHostPortForNodeAt(bdbPort)); + _testcase.setVirtualHostConfigurationProperty(_vhostStoreConfigKeyPrefix + "highAvailability.helperHostPort", getHelperHostPort()); } public String getIpAddressOfBrokerHost() @@ -369,24 +371,24 @@ public class HATestClusterCreator } } - private void collectConfig(final int brokerPortNumber, XMLConfiguration testConfiguration, XMLConfiguration testVirtualhosts) + private void collectConfig(final int brokerPortNumber, TestBrokerConfiguration testConfiguration, XMLConfiguration testVirtualhosts) { - _brokerConfigurations.put(brokerPortNumber, new BrokerConfigHolder((XMLConfiguration) testConfiguration.clone(), + _brokerConfigurations.put(brokerPortNumber, new BrokerConfigHolder(testConfiguration, (XMLConfiguration) testVirtualhosts.clone())); } public class BrokerConfigHolder { - private final XMLConfiguration _testConfiguration; + private final TestBrokerConfiguration _testConfiguration; private final XMLConfiguration _testVirtualhosts; - public BrokerConfigHolder(XMLConfiguration testConfiguration, XMLConfiguration testVirtualhosts) + public BrokerConfigHolder(TestBrokerConfiguration testConfiguration, XMLConfiguration testVirtualhosts) { _testConfiguration = testConfiguration; _testVirtualhosts = testVirtualhosts; } - public XMLConfiguration getTestConfiguration() + public TestBrokerConfiguration getTestConfiguration() { return _testConfiguration; } @@ -416,7 +418,7 @@ public class HATestClusterCreator public String getStoreConfigKeyPrefix() { - return _storeConfigKeyPrefix; + return _vhostStoreConfigKeyPrefix; } diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/MessageStoreCreatorTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/MessageStoreCreatorTest.java new file mode 100644 index 0000000000..d33eb868c2 --- /dev/null +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/MessageStoreCreatorTest.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store.berkeleydb; + +import org.apache.qpid.server.store.MemoryMessageStore; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.MessageStoreCreator; +import org.apache.qpid.server.store.berkeleydb.BDBHAMessageStore; +import org.apache.qpid.server.store.berkeleydb.BDBMessageStore; +import org.apache.qpid.server.store.derby.DerbyMessageStore; +import org.apache.qpid.test.utils.QpidTestCase; + +public class MessageStoreCreatorTest extends QpidTestCase +{ + private static final String[] STORE_TYPES = {MemoryMessageStore.TYPE, DerbyMessageStore.TYPE, BDBMessageStore.TYPE, BDBHAMessageStore.TYPE}; + + public void testMessageStoreCreator() + { + MessageStoreCreator messageStoreCreator = new MessageStoreCreator(); + for (String type : STORE_TYPES) + { + MessageStore store = messageStoreCreator.createMessageStore(type); + assertNotNull("Store of type " + type + " is not created", store); + } + } +} diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java index cd2654f79f..b2b28b3c2d 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java @@ -20,7 +20,14 @@ */ package org.apache.qpid.server.store.berkeleydb.upgrade; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.NONEXCLUSIVE_WITH_ERRONEOUS_OWNER; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.NON_DURABLE_QUEUE_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.PRIORITY_QUEUE_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_WITH_DLQ_NAME; + import java.io.File; +import java.io.InputStream; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.subjects.TestBlankSubject; @@ -51,15 +58,15 @@ public abstract class AbstractUpgradeTestCase extends QpidTestCase } } - public static final String[] QUEUE_NAMES = { "clientid:myDurSubName", "clientid:mySelectorDurSubName", "myUpgradeQueue", - "queue-non-durable", "nonexclusive-with-erroneous-owner" }; - public static int[] QUEUE_SIZES = { 1, 1, 10, 3, 0}; - public static int TOTAL_MESSAGE_NUMBER = 15; + public static final String[] QUEUE_NAMES = { "clientid:myDurSubName", "clientid:mySelectorDurSubName", QUEUE_NAME, NON_DURABLE_QUEUE_NAME, + NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, PRIORITY_QUEUE_NAME, QUEUE_WITH_DLQ_NAME, QUEUE_WITH_DLQ_NAME + "_DLQ" }; + public static int[] QUEUE_SIZES = { 1, 1, 10, 3, 0, 0, 0, 1}; + public static int TOTAL_MESSAGE_NUMBER = 16; protected static final LogSubject LOG_SUBJECT = new TestBlankSubject(); - // one binding per exchange - protected static final int TOTAL_BINDINGS = QUEUE_NAMES.length * 2; - protected static final int TOTAL_EXCHANGES = 5; + // myQueueWithDLQ_DLQ is not bound to the default exchange + protected static final int TOTAL_BINDINGS = QUEUE_NAMES.length * 2 - 1; + protected static final int TOTAL_EXCHANGES = 6; private File _storeLocation; protected Environment _environment; @@ -105,10 +112,24 @@ public abstract class AbstractUpgradeTestCase extends QpidTestCase private File copyStore(String storeDirectoryName) throws Exception { - String src = getClass().getClassLoader().getResource("upgrade/" + storeDirectoryName).toURI().getPath(); File storeLocation = new File(new File(TMP_FOLDER), "test-store"); deleteDirectoryIfExists(storeLocation); - FileUtils.copyRecursive(new File(src), new File(TMP_FOLDER)); + storeLocation.mkdirs(); + int index = 0; + String prefix = "0000000"; + String extension = ".jdb"; + InputStream is = null; + do + { + String fileName = prefix + index + extension; + is = getClass().getClassLoader().getResourceAsStream("upgrade/" + storeDirectoryName + "/test-store/" + fileName); + if (is != null) + { + FileUtils.copy(is, new File(storeLocation, fileName)); + } + index++; + } + while (is != null); return storeLocation; } diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java index 65a8bb03fb..500fb0a919 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java @@ -20,6 +20,13 @@ */ package org.apache.qpid.server.store.berkeleydb.upgrade; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.NONEXCLUSIVE_WITH_ERRONEOUS_OWNER; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.NON_DURABLE_QUEUE_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_WITH_DLQ_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.SELECTOR_TOPIC_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.TOPIC_NAME; + import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; @@ -34,7 +41,6 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.BindingRecord; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.BindingTuple; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom4To5.MessageContentKey; @@ -50,9 +56,6 @@ import com.sleepycat.je.Transaction; public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase { - private static final String NON_DURABLE_QUEUE = BDBStoreUpgradeTestPreparer.NON_DURABLE_QUEUE_NAME; - private static final String DURABLE_QUEUE = BDBStoreUpgradeTestPreparer.QUEUE_NAME; - private static final String NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER = "nonexclusive-with-erroneous-owner"; private static final String DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR = "clientid:mySelectorDurSubName"; private static final String DURABLE_SUBSCRIPTION_QUEUE = "clientid:myDurSubName"; private static final String EXCHANGE_DB_NAME = "exchangeDb_v5"; @@ -85,15 +88,14 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase final List queueBindings = loadBindings(); - assertEquals("Unxpected list size", TOTAL_BINDINGS, queueBindings.size()); - assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE, "amq.topic", BDBStoreUpgradeTestPreparer.TOPIC_NAME, ""); - assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, "amq.topic", - BDBStoreUpgradeTestPreparer.SELECTOR_TOPIC_NAME, "testprop='true'"); - assertBindingRecord(queueBindings, DURABLE_QUEUE, "amq.direct", DURABLE_QUEUE, null); - assertBindingRecord(queueBindings, NON_DURABLE_QUEUE, "amq.direct", NON_DURABLE_QUEUE, null); - assertBindingRecord(queueBindings, NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, "amq.direct", NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, null); + assertEquals("Unxpected bindings size", TOTAL_BINDINGS, queueBindings.size()); + assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE, "amq.topic", TOPIC_NAME, ""); + assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, "amq.topic", SELECTOR_TOPIC_NAME, "testprop='true'"); + assertBindingRecord(queueBindings, QUEUE_NAME, "amq.direct", QUEUE_NAME, null); + assertBindingRecord(queueBindings, NON_DURABLE_QUEUE_NAME, "amq.direct", NON_DURABLE_QUEUE_NAME, null); + assertBindingRecord(queueBindings, NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, "amq.direct", NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, null); - assertQueueHasOwner(NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description"); + assertQueueHasOwner(NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description"); assertContent(); } @@ -102,26 +104,29 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase { UpgradeFrom4To5 upgrade = new UpgradeFrom4To5(); upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.NO), getVirtualHostName()); - assertQueues(new HashSet(Arrays.asList(DURABLE_SUBSCRIPTION_QUEUE, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, DURABLE_QUEUE, NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER))); + HashSet queues = new HashSet(Arrays.asList(QUEUE_NAMES)); + assertTrue(NON_DURABLE_QUEUE_NAME + " should be in the list of queues" , queues.remove(NON_DURABLE_QUEUE_NAME)); + + assertQueues(queues); - assertDatabaseRecordCount(DELIVERY_DB_NAME, 12); - assertDatabaseRecordCount(MESSAGE_META_DATA_DB_NAME, 12); + assertDatabaseRecordCount(DELIVERY_DB_NAME, 13); + assertDatabaseRecordCount(MESSAGE_META_DATA_DB_NAME, 13); assertDatabaseRecordCount(EXCHANGE_DB_NAME, TOTAL_EXCHANGES); assertQueueMessages(DURABLE_SUBSCRIPTION_QUEUE, 1); assertQueueMessages(DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, 1); - assertQueueMessages(DURABLE_QUEUE, 10); + assertQueueMessages(QUEUE_NAME, 10); + assertQueueMessages(QUEUE_WITH_DLQ_NAME + "_DLQ", 1); final List queueBindings = loadBindings(); assertEquals("Unxpected list size", TOTAL_BINDINGS - 2, queueBindings.size()); - assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE, "amq.topic", BDBStoreUpgradeTestPreparer.TOPIC_NAME, - ""); + assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE, "amq.topic", TOPIC_NAME, ""); assertBindingRecord(queueBindings, DURABLE_SUBSCRIPTION_QUEUE_WITH_SELECTOR, "amq.topic", - BDBStoreUpgradeTestPreparer.SELECTOR_TOPIC_NAME, "testprop='true'"); - assertBindingRecord(queueBindings, DURABLE_QUEUE, "amq.direct", DURABLE_QUEUE, null); + SELECTOR_TOPIC_NAME, "testprop='true'"); + assertBindingRecord(queueBindings, QUEUE_NAME, "amq.direct", QUEUE_NAME, null); - assertQueueHasOwner(NON_EXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description"); + assertQueueHasOwner(NONEXCLUSIVE_WITH_ERRONEOUS_OWNER, "misused-owner-as-description"); assertContent(); } diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java index 2d2a6b20a2..c33d427868 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.server.store.berkeleydb.upgrade; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.PRIORITY_QUEUE_NAME; +import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_WITH_DLQ_NAME; import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.CONFIGURED_OBJECTS_DB_NAME; import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NEW_CONTENT_DB_NAME; import static org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NEW_DELIVERY_DB_NAME; @@ -42,6 +44,7 @@ import java.util.UUID; import org.apache.log4j.Logger; import org.apache.qpid.server.model.Binding; import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.AMQQueueFactory; @@ -50,7 +53,6 @@ import org.apache.qpid.server.store.berkeleydb.tuple.XidBinding; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.CompoundKey; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.CompoundKeyBinding; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.ConfiguredObjectBinding; -import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.UpgradeConfiguredObjectRecord; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewDataBinding; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewPreparedTransaction; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewPreparedTransactionBinding; @@ -60,6 +62,7 @@ import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.NewRecord import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OldPreparedTransaction; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OldPreparedTransactionBinding; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.OldRecordImpl; +import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.UpgradeConfiguredObjectRecord; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.UpgradeUUIDBinding; import org.apache.qpid.server.util.MapJsonSerializer; @@ -115,8 +118,8 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase upgrade.performUpgrade(_environment, discardMessageInteractionHandler, getVirtualHostName()); - assertDatabaseRecordCount(NEW_METADATA_DB_NAME, 11); - assertDatabaseRecordCount(NEW_CONTENT_DB_NAME, 11); + assertDatabaseRecordCount(NEW_METADATA_DB_NAME, 12); + assertDatabaseRecordCount(NEW_CONTENT_DB_NAME, 12); assertConfiguredObjects(); assertQueueEntries(); @@ -264,17 +267,17 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase private void assertDatabaseRecordCounts() { - assertDatabaseRecordCount(CONFIGURED_OBJECTS_DB_NAME, 12); - assertDatabaseRecordCount(NEW_DELIVERY_DB_NAME, 12); + assertDatabaseRecordCount(CONFIGURED_OBJECTS_DB_NAME, 21); + assertDatabaseRecordCount(NEW_DELIVERY_DB_NAME, 13); - assertDatabaseRecordCount(NEW_METADATA_DB_NAME, 12); - assertDatabaseRecordCount(NEW_CONTENT_DB_NAME, 12); + assertDatabaseRecordCount(NEW_METADATA_DB_NAME, 13); + assertDatabaseRecordCount(NEW_CONTENT_DB_NAME, 13); } private void assertConfiguredObjects() { Map configuredObjects = loadConfiguredObjects(); - assertEquals("Unexpected number of configured objects", 12, configuredObjects.size()); + assertEquals("Unexpected number of configured objects", 21, configuredObjects.size()); Set> expected = new HashSet>(12); List expectedBindingIDs = new ArrayList(); @@ -282,8 +285,26 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase expected.add(createExpectedQueueMap("myUpgradeQueue", Boolean.FALSE, null, null)); expected.add(createExpectedQueueMap("clientid:mySelectorDurSubName", Boolean.TRUE, "clientid", null)); expected.add(createExpectedQueueMap("clientid:myDurSubName", Boolean.TRUE, "clientid", null)); - expected.add(createExpectedQueueMap("nonexclusive-with-erroneous-owner", Boolean.FALSE, null, - Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, "misused-owner-as-description"))); + + final Map queueWithOwnerArguments = new HashMap(); + queueWithOwnerArguments.put("x-qpid-priorities", 10); + queueWithOwnerArguments.put(AMQQueueFactory.X_QPID_DESCRIPTION, "misused-owner-as-description"); + expected.add(createExpectedQueueMap("nonexclusive-with-erroneous-owner", Boolean.FALSE, null,queueWithOwnerArguments)); + + final Map priorityQueueArguments = new HashMap(); + priorityQueueArguments.put("x-qpid-priorities", 10); + expected.add(createExpectedQueueMap(PRIORITY_QUEUE_NAME, Boolean.FALSE, null, priorityQueueArguments)); + + final Map queueWithDLQArguments = new HashMap(); + queueWithDLQArguments.put("x-qpid-dlq-enabled", true); + queueWithDLQArguments.put("x-qpid-maximum-delivery-count", 2); + expected.add(createExpectedQueueMap(QUEUE_WITH_DLQ_NAME, Boolean.FALSE, null, queueWithDLQArguments)); + + final Map dlqArguments = new HashMap(); + dlqArguments.put("x-qpid-dlq-enabled", false); + dlqArguments.put("x-qpid-maximum-delivery-count", 0); + expected.add(createExpectedQueueMap(QUEUE_WITH_DLQ_NAME + "_DLQ", Boolean.FALSE, null, dlqArguments)); + expected.add(createExpectedExchangeMap(QUEUE_WITH_DLQ_NAME + "_DLE", "fanout")); expected.add(createExpectedQueueBindingMapAndID("myUpgradeQueue","myUpgradeQueue", "<>", null, expectedBindingIDs)); expected.add(createExpectedQueueBindingMapAndID("myUpgradeQueue", "myUpgradeQueue", "amq.direct", null, expectedBindingIDs)); @@ -296,6 +317,13 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase expected.add(createExpectedQueueBindingMapAndID("nonexclusive-with-erroneous-owner", "nonexclusive-with-erroneous-owner", "amq.direct", null, expectedBindingIDs)); expected.add(createExpectedQueueBindingMapAndID("nonexclusive-with-erroneous-owner","nonexclusive-with-erroneous-owner", "<>", null, expectedBindingIDs)); + expected.add(createExpectedQueueBindingMapAndID(PRIORITY_QUEUE_NAME, PRIORITY_QUEUE_NAME, "<>", null, expectedBindingIDs)); + expected.add(createExpectedQueueBindingMapAndID(PRIORITY_QUEUE_NAME, PRIORITY_QUEUE_NAME, "amq.direct", null, expectedBindingIDs)); + + expected.add(createExpectedQueueBindingMapAndID(QUEUE_WITH_DLQ_NAME, QUEUE_WITH_DLQ_NAME, "<>", null, expectedBindingIDs)); + expected.add(createExpectedQueueBindingMapAndID(QUEUE_WITH_DLQ_NAME, QUEUE_WITH_DLQ_NAME, "amq.direct", null, expectedBindingIDs)); + expected.add(createExpectedQueueBindingMapAndID(QUEUE_WITH_DLQ_NAME + "_DLQ", "dlq", QUEUE_WITH_DLQ_NAME + "_DLE", null, expectedBindingIDs)); + Set expectedTypes = new HashSet(); expectedTypes.add(Queue.class.getName()); expectedTypes.add(Exchange.class.getName()); @@ -305,7 +333,9 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase { UpgradeConfiguredObjectRecord object = entry.getValue(); Map deserialized = jsonSerializer.deserialize(object.getAttributes()); - assertTrue("Unexpected entry:" + object.getAttributes(), expected.remove(deserialized)); + + assertTrue("Unexpected entry in a store - json [" + object.getAttributes() + "], map [" + deserialized + "]", + expected.remove(deserialized)); String type = object.getType(); assertTrue("Unexpected type:" + type, expectedTypes.contains(type)); UUID key = entry.getKey(); @@ -350,7 +380,7 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase return expectedQueueBinding; } - private Map createExpectedQueueMap(String name, boolean exclusiveFlag, String owner, Map argumentMap) + private Map createExpectedQueueMap(String name, boolean exclusiveFlag, String owner, Map argumentMap) { Map expectedQueueEntry = new HashMap(); expectedQueueEntry.put(Queue.NAME, name); @@ -363,6 +393,15 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase return expectedQueueEntry; } + private Map createExpectedExchangeMap(String name, String type) + { + Map expectedExchnageEntry = new HashMap(); + expectedExchnageEntry.put(Exchange.NAME, name); + expectedExchnageEntry.put(Exchange.TYPE, type); + expectedExchnageEntry.put(Exchange.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name()); + return expectedExchnageEntry; + } + private Map loadConfiguredObjects() { final Map configuredObjectsRecords = new HashMap(); diff --git a/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb b/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb index f5ed9aa5a2..cfc1f05d28 100644 Binary files a/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb and b/java/bdbstore/src/test/resources/upgrade/bdbstore-v4/test-store/00000000.jdb differ diff --git a/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb b/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb index f5ed9aa5a2..cfc1f05d28 100644 Binary files a/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb and b/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000000.jdb differ diff --git a/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb b/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb index d5ae8c1096..4b45ff61e6 100644 Binary files a/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb and b/java/bdbstore/src/test/resources/upgrade/bdbstore-v5/test-store/00000001.jdb differ diff --git a/java/broker-plugins/access-control/MANIFEST.MF b/java/broker-plugins/access-control/MANIFEST.MF deleted file mode 100644 index a8fb99995e..0000000000 --- a/java/broker-plugins/access-control/MANIFEST.MF +++ /dev/null @@ -1,41 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Qpid Broker-Plugins Access Control -Bundle-SymbolicName: broker-plugins-access-control -Bundle-Description: Access control plugin for Qpid. -Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt -Bundle-DocURL: http://qpid.apache.org/acl.html -Bundle-Version: 1.0.0 -Bundle-Activator: org.apache.qpid.server.security.access.plugins.AccessControlActivator -Bundle-RequiredExecutionEnvironment: JavaSE-1.5 -Bundle-ClassPath: . -Bundle-ActivationPolicy: lazy -Import-Package: org.apache.qpid, - org.apache.qpid.exchange, - org.apache.qpid.framing, - org.apache.qpid.protocol, - org.apache.qpid.server.configuration, - org.apache.qpid.server.configuration.plugins, - org.apache.qpid.server.exchange, - org.apache.qpid.server.logging, - org.apache.qpid.server.logging.actors, - org.apache.qpid.server.logging.subjects, - org.apache.qpid.server.plugins, - org.apache.qpid.server.queue, - org.apache.qpid.server.registry, - org.apache.qpid.server.security, - org.apache.qpid.server.security.access, - org.apache.qpid.server.virtualhost, - org.apache.qpid.util, - org.apache.commons.configuration;version=1.0.0, - org.apache.commons.lang;version=1.0.0, - org.apache.commons.lang.builder;version=1.0.0, - org.apache.log4j;version=1.0.0, - javax.management;version=1.0.0, - javax.management.openmbean;version=1.0.0, - javax.security.auth;version=1.0.0, - org.osgi.util.tracker;version=1.0.0, - org.osgi.framework;version=1.3 -Private-Package: org.apache.qpid.server.security.access.config, - org.apache.qpid.server.security.access.logging -Export-Package: org.apache.qpid.server.security.access.plugins diff --git a/java/broker-plugins/access-control/build.xml b/java/broker-plugins/access-control/build.xml index df3346788c..4debdcb95a 100644 --- a/java/broker-plugins/access-control/build.xml +++ b/java/broker-plugins/access-control/build.xml @@ -18,13 +18,13 @@ --> - + - - + + diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java index f04dd38aca..f87374ac80 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AbstractConfiguration.java @@ -22,13 +22,8 @@ package org.apache.qpid.server.security.access.config; import java.io.File; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; - public abstract class AbstractConfiguration implements ConfigurationFile { - private static final Logger _logger = Logger.getLogger(ConfigurationFile.class); - private File _file; private RuleSet _config; @@ -42,7 +37,7 @@ public abstract class AbstractConfiguration implements ConfigurationFile return _file; } - public RuleSet load() throws ConfigurationException + public RuleSet load() { _config = new RuleSet(); return _config; diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclAction.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclAction.java new file mode 100644 index 0000000000..e4bf21a082 --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclAction.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.access.config; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.access.firewall.FirewallRule; + +public class AclAction +{ + private Action _action; + private FirewallRule _firewallRule; + + public AclAction(Operation operation, ObjectType object, AclRulePredicates predicates) + { + _action = new Action(operation, object, predicates.getObjectProperties()); + _firewallRule = predicates.getFirewallRule(); + } + + public AclAction(Operation operation) + { + _action = new Action(operation); + } + + public AclAction(Operation operation, ObjectType object, ObjectProperties properties) + { + _action = new Action(operation, object, properties); + } + + public FirewallRule getFirewallRule() + { + return _firewallRule; + } + + public Action getAction() + { + return _action; + } + + public boolean isAllowed() + { + return _action.isAllowed(); + } + + @Override + public int hashCode() + { + return new HashCodeBuilder() + .append(_action) + .append(_firewallRule).toHashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (obj == this) + { + return true; + } + if (obj.getClass() != getClass()) + { + return false; + } + AclAction rhs = (AclAction) obj; + return new EqualsBuilder() + .append(_action, rhs._action) + .append(_firewallRule, rhs._firewallRule).isEquals(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append(_action) + .append(_firewallRule).toString(); + } +} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java new file mode 100644 index 0000000000..45af85be6c --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.access.config; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.log4j.Logger; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectProperties.Property; +import org.apache.qpid.server.security.access.firewall.FirewallRule; +import org.apache.qpid.server.security.access.firewall.FirewallRuleFactory; + +/** + * Represents the predicates on an ACL rule by combining predicates relating to the object being operated on + * (e.g. name=foo) with firewall rules. + */ +public class AclRulePredicates +{ + private static final Logger _logger = Logger.getLogger(AclRulePredicates.class); + + private static final String SEPARATOR = ","; + + private ObjectProperties _properties = new ObjectProperties(); + + private FirewallRule _firewallRule; + + private FirewallRuleFactory _firewallRuleFactory = new FirewallRuleFactory(); + + public void parse(String key, String value) + { + ObjectProperties.Property property = ObjectProperties.Property.parse(key); + + if(property == Property.FROM_HOSTNAME) + { + checkFirewallRuleNotAlreadyDefined(key, value); + _firewallRule = _firewallRuleFactory.createForHostname(value.split(SEPARATOR)); + } + else if(property == Property.FROM_NETWORK) + { + checkFirewallRuleNotAlreadyDefined(key, value); + _firewallRule = _firewallRuleFactory.createForNetwork(value.split(SEPARATOR)); + } + else + { + _properties.put(property, value); + } + + if (_logger.isDebugEnabled()) + { + _logger.debug("Parsed " + property + " with value " + value); + } + } + + private void checkFirewallRuleNotAlreadyDefined(String key, String value) + { + if(_firewallRule != null) + { + throw new IllegalStateException( + "Cannot parse " + key + "=" + value + + " because firewall rule " + _firewallRule + " has already been defined"); + } + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append(_properties) + .append(_firewallRule).toString(); + } + + public FirewallRule getFirewallRule() + { + return _firewallRule; + } + + public ObjectProperties getObjectProperties() + { + return _properties; + } + + void setFirewallRuleFactory(FirewallRuleFactory firewallRuleFactory) + { + _firewallRuleFactory = firewallRuleFactory; + } +} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Action.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Action.java index b887d1e079..4fff0bebf5 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Action.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Action.java @@ -20,8 +20,6 @@ */ package org.apache.qpid.server.security.access.config; -import java.util.Comparator; - import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; @@ -32,7 +30,7 @@ import org.apache.qpid.server.security.access.Operation; /** * An access control v2 rule action. - * + * * An action consists of an {@link Operation} on an {@link ObjectType} with certain properties, stored in a {@link java.util.Map}. * The operation and object should be an allowable combination, based on the {@link ObjectType#isAllowed(Operation)} * method of the object, which is exposed as the {@link #isAllowed()} method here. The internal {@link #propertiesMatch(Map)} @@ -45,104 +43,96 @@ import org.apache.qpid.server.security.access.Operation; */ public class Action { - private Operation _operation; - private ObjectType _object; - private ObjectProperties _properties; - + private final Operation _operation; + private final ObjectType _object; + private final ObjectProperties _properties; + public Action(Operation operation) { this(operation, ObjectType.ALL); } - + public Action(Operation operation, ObjectType object, String name) { this(operation, object, new ObjectProperties(name)); } - + public Action(Operation operation, ObjectType object) { this(operation, object, ObjectProperties.EMPTY); } - + public Action(Operation operation, ObjectType object, ObjectProperties properties) { - setOperation(operation); - setObjectType(object); - setProperties(properties); + _operation = operation; + _object = object; + _properties = properties; } - + public Operation getOperation() { return _operation; } - public void setOperation(Operation operation) - { - _operation = operation; - } - public ObjectType getObjectType() { return _object; } - public void setObjectType(ObjectType object) - { - _object = object; - } - public ObjectProperties getProperties() { return _properties; } - - public void setProperties(ObjectProperties properties) - { - _properties = properties; - } - + public boolean isAllowed() { return _object.isAllowed(_operation); } - /** @see Comparable#compareTo(Object) */ public boolean matches(Action a) { - return ((Operation.ALL == a.getOperation() || getOperation() == a.getOperation()) - && (ObjectType.ALL == a.getObjectType() || getObjectType() == a.getObjectType()) - && _properties.matches(a.getProperties())); + if (!operationsMatch(a)) + { + return false; + } + + if (!objectTypesMatch(a)) + { + return false; + } + + if (!propertiesMatch(a)) + { + return false; + } + + return true; + } + + private boolean operationsMatch(Action a) + { + return Operation.ALL == a.getOperation() || getOperation() == a.getOperation(); } - /** - * An ordering based on specificity - * - * @see Comparator#compare(Object, Object) - */ - public class Specificity implements Comparator + private boolean objectTypesMatch(Action a) { - public int compare(Action a, Action b) + return ObjectType.ALL == a.getObjectType() || getObjectType() == a.getObjectType(); + } + + private boolean propertiesMatch(Action a) + { + boolean propertiesMatch = false; + if (_properties != null) + { + propertiesMatch = _properties.matches(a.getProperties()); + } + else if (a.getProperties() == null) { - if (a.getOperation() == Operation.ALL && b.getOperation() != Operation.ALL) - { - return 1; // B is more specific - } - else if (b.getOperation() == Operation.ALL && a.getOperation() != Operation.ALL) - { - return 1; // A is more specific - } - else if (a.getOperation() == b.getOperation()) - { - return 1; // b is more specific - } - else // Different operations - { - return a.getOperation().compareTo(b.getOperation()); // Arbitrary - } + propertiesMatch = true; } + return propertiesMatch; } - /** @see Object#equals(Object) */ @Override public boolean equals(Object o) { @@ -151,26 +141,24 @@ public class Action return false; } Action a = (Action) o; - + return new EqualsBuilder() .append(_operation, a.getOperation()) .append(_object, a.getObjectType()) - .appendSuper(_properties.equals(a.getProperties())) + .append(_properties, a.getProperties()) .isEquals(); } - /** @see Object#hashCode() */ @Override public int hashCode() { return new HashCodeBuilder() .append(_operation) - .append(_operation) + .append(_object) .append(_properties) .toHashCode(); } - /** @see Object#toString() */ @Override public String toString() { diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ClientAction.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ClientAction.java new file mode 100644 index 0000000000..fed20a56c8 --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ClientAction.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.access.config; + +import java.net.InetAddress; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.access.firewall.FirewallRule; + +/** + * I represent an {@link Action} taken by a client from a known address. The address is used to + * determine if I match an {@link AclAction}, which may contain firewall rules. + */ +public class ClientAction +{ + private Action _clientAction; + + public ClientAction(Action clientAction) + { + _clientAction = clientAction; + } + + public ClientAction(Operation operation, ObjectType objectType, ObjectProperties properties) + { + _clientAction = new Action(operation, objectType, properties); + } + + public boolean matches(AclAction ruleAction, InetAddress addressOfClient) + { + return _clientAction.matches(ruleAction.getAction()) + && addressOfClientMatches(ruleAction, addressOfClient); + } + + private boolean addressOfClientMatches(AclAction ruleAction, InetAddress addressOfClient) + { + FirewallRule firewallRule = ruleAction.getFirewallRule(); + if(firewallRule == null || addressOfClient == null) + { + return true; + } + else + { + return firewallRule.matches(addressOfClient); + } + } + + public Operation getOperation() + { + return _clientAction.getOperation(); + } + + public ObjectType getObjectType() + { + return _clientAction.getObjectType(); + } + + public ObjectProperties getProperties() + { + return _clientAction.getProperties(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append(_clientAction).toString(); + } +} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java index 8b1a00259b..966c32e24e 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/ConfigurationFile.java @@ -22,7 +22,7 @@ package org.apache.qpid.server.security.access.config; import java.io.File; -import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.configuration.IllegalConfigurationException; public interface ConfigurationFile { @@ -33,19 +33,17 @@ public interface ConfigurationFile /** * Load this configuration file's contents into a {@link RuleSet}. - * - * @throws ConfigurationException if the configuration file has errors. + * @throws IllegalConfigurationException if the configuration file has errors. * @throws IllegalArgumentException if individual tokens cannot be parsed. */ - RuleSet load() throws ConfigurationException; + RuleSet load() throws IllegalConfigurationException; /** * Reload this configuration file's contents. - * - * @throws ConfigurationException if the configuration file has errors. + * @throws IllegalConfigurationException if the configuration file has errors. * @throws IllegalArgumentException if individual tokens cannot be parsed. */ - RuleSet reload() throws ConfigurationException; + RuleSet reload() throws IllegalConfigurationException; RuleSet getConfiguration(); diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java index 9a08eb6499..ab309c54ce 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java @@ -1,5 +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 @@ -7,16 +7,16 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 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.config; @@ -32,55 +32,65 @@ import java.util.List; import java.util.Map; import java.util.Stack; -import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.lang.StringUtils; -import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.security.access.ObjectType; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.access.Permission; public class PlainConfiguration extends AbstractConfiguration { + private static final Logger _logger = Logger.getLogger(PlainConfiguration.class); + public static final Character COMMENT = '#'; public static final Character CONTINUATION = '\\'; - public static final String GROUP = "group"; public static final String ACL = "acl"; public static final String CONFIG = "config"; - public static final String UNRECOGNISED_INITIAL_MSG = "Unrecognised initial token '%s' at line %d"; - public static final String NOT_ENOUGH_TOKENS_MSG = "Not enough tokens at line %d"; - public static final String NUMBER_NOT_ALLOWED_MSG = "Number not allowed before '%s' at line %d"; - public static final String CANNOT_LOAD_MSG = "Cannot load config file %s"; - public static final String PREMATURE_CONTINUATION_MSG = "Premature continuation character at line %d"; - public static final String PREMATURE_EOF_MSG = "Premature end of file reached at line %d"; - public static final String PARSE_TOKEN_FAILED_MSG = "Failed to parse token at line %d"; - public static final String CONFIG_NOT_FOUND_MSG = "Cannot find config file %s"; - public static final String NOT_ENOUGH_GROUP_MSG = "Not enough data for a group at line %d"; - public static final String NOT_ENOUGH_ACL_MSG = "Not enough data for an acl at line %d"; - public static final String NOT_ENOUGH_CONFIG_MSG = "Not enough data for config at line %d"; - public static final String BAD_ACL_RULE_NUMBER_MSG = "Invalid rule number at line %d"; - public static final String PROPERTY_KEY_ONLY_MSG = "Incomplete property (key only) at line %d"; - public static final String PROPERTY_NO_EQUALS_MSG = "Incomplete property (no equals) at line %d"; - public static final String PROPERTY_NO_VALUE_MSG = "Incomplete property (no value) at line %d"; - + static final String UNRECOGNISED_INITIAL_MSG = "Unrecognised initial token '%s' at line %d"; + static final String NOT_ENOUGH_TOKENS_MSG = "Not enough tokens at line %d"; + static final String NUMBER_NOT_ALLOWED_MSG = "Number not allowed before '%s' at line %d"; + static final String CANNOT_LOAD_MSG = "Cannot load config file %s"; + static final String CANNOT_CLOSE_MSG = "Cannot close config file %s"; + static final String PREMATURE_CONTINUATION_MSG = "Premature continuation character at line %d"; + static final String PREMATURE_EOF_MSG = "Premature end of file reached at line %d"; + static final String PARSE_TOKEN_FAILED_MSG = "Failed to parse token at line %d"; + static final String CONFIG_NOT_FOUND_MSG = "Cannot find config file %s"; + static final String NOT_ENOUGH_ACL_MSG = "Not enough data for an acl at line %d"; + static final String NOT_ENOUGH_CONFIG_MSG = "Not enough data for config at line %d"; + static final String BAD_ACL_RULE_NUMBER_MSG = "Invalid rule number at line %d"; + static final String PROPERTY_KEY_ONLY_MSG = "Incomplete property (key only) at line %d"; + static final String PROPERTY_NO_EQUALS_MSG = "Incomplete property (no equals) at line %d"; + static final String PROPERTY_NO_VALUE_MSG = "Incomplete property (no value) at line %d"; + private StreamTokenizer _st; public PlainConfiguration(File file) { super(file); } - + @Override - public RuleSet load() throws ConfigurationException + public RuleSet load() { RuleSet ruleSet = super.load(); - + + File file = getFile(); + FileReader fileReader = null; + try { - _st = new StreamTokenizer(new BufferedReader(new FileReader(getFile()))); + if(_logger.isDebugEnabled()) + { + _logger.debug("About to load ACL file " + file); + } + + fileReader = new FileReader(file); + _st = new StreamTokenizer(new BufferedReader(fileReader)); _st.resetSyntax(); // setup the tokenizer - + _st.commentChar(COMMENT); // single line comments _st.eolIsSignificant(true); // return EOL as a token _st.ordinaryChar('='); // equals is a token @@ -97,7 +107,7 @@ public class PlainConfiguration extends AbstractConfiguration _st.wordChars('*', '*'); // star _st.wordChars('@', '@'); // at _st.wordChars(':', ':'); // colon - + // parse the acl file lines Stack stack = new Stack(); int current; @@ -111,21 +121,21 @@ public class PlainConfiguration extends AbstractConfiguration { break; // blank line } - + // pull out the first token from the bottom of the stack and check arguments exist String first = stack.firstElement(); stack.removeElementAt(0); if (stack.isEmpty()) { - throw new ConfigurationException(String.format(NOT_ENOUGH_TOKENS_MSG, getLine())); + throw new IllegalConfigurationException(String.format(NOT_ENOUGH_TOKENS_MSG, getLine())); } - + // check for and parse optional initial number for ACL lines Integer number = null; if (StringUtils.isNumeric(first)) { // set the acl number and get the next element - number = Integer.valueOf(first); + number = Integer.valueOf(first); first = stack.firstElement(); stack.removeElementAt(0); } @@ -136,9 +146,9 @@ public class PlainConfiguration extends AbstractConfiguration } else if (number == null) { - if (StringUtils.equalsIgnoreCase(GROUP, first)) + if(StringUtils.equalsIgnoreCase("GROUP", first)) { - parseGroup(stack); + throw new IllegalConfigurationException(String.format("GROUP keyword not supported. Groups should defined via a Group Provider, not in the ACL file.", getLine())); } else if (StringUtils.equalsIgnoreCase(CONFIG, first)) { @@ -146,14 +156,14 @@ public class PlainConfiguration extends AbstractConfiguration } else { - throw new ConfigurationException(String.format(UNRECOGNISED_INITIAL_MSG, first, getLine())); + throw new IllegalConfigurationException(String.format(UNRECOGNISED_INITIAL_MSG, first, getLine())); } } else { - throw new ConfigurationException(String.format(NUMBER_NOT_ALLOWED_MSG, first, getLine())); + throw new IllegalConfigurationException(String.format(NUMBER_NOT_ALLOWED_MSG, first, getLine())); } - + // reset stack, start next line stack.clear(); break; @@ -171,9 +181,9 @@ public class PlainConfiguration extends AbstractConfiguration { break; // continue reading next line } - + // invalid location for continuation character (add one to line beacuse we ate the EOL) - throw new ConfigurationException(String.format(PREMATURE_CONTINUATION_MSG, getLine() + 1)); + throw new IllegalConfigurationException(String.format(PREMATURE_CONTINUATION_MSG, getLine() + 1)); } else if (_st.ttype == '\'' || _st.ttype == '"') { @@ -185,54 +195,59 @@ public class PlainConfiguration extends AbstractConfiguration } } } while (current != StreamTokenizer.TT_EOF); - + if (!stack.isEmpty()) { - throw new ConfigurationException(String.format(PREMATURE_EOF_MSG, getLine())); + throw new IllegalConfigurationException(String.format(PREMATURE_EOF_MSG, getLine())); } } catch (IllegalArgumentException iae) { - throw new ConfigurationException(String.format(PARSE_TOKEN_FAILED_MSG, getLine()), iae); + throw new IllegalConfigurationException(String.format(PARSE_TOKEN_FAILED_MSG, getLine()), iae); } catch (FileNotFoundException fnfe) { - throw new ConfigurationException(String.format(CONFIG_NOT_FOUND_MSG, getFile().getName()), fnfe); + throw new IllegalConfigurationException(String.format(CONFIG_NOT_FOUND_MSG, file.getName()), fnfe); } catch (IOException ioe) { - throw new ConfigurationException(String.format(CANNOT_LOAD_MSG, getFile().getName()), ioe); + throw new IllegalConfigurationException(String.format(CANNOT_LOAD_MSG, file.getName()), ioe); } - - return ruleSet; - } - - private void parseGroup(List args) throws ConfigurationException - { - if (args.size() < 2) + finally { - throw new ConfigurationException(String.format(NOT_ENOUGH_GROUP_MSG, getLine())); + if(fileReader != null) + { + try + { + fileReader.close(); + } + catch (IOException e) + { + throw new IllegalConfigurationException(String.format(CANNOT_CLOSE_MSG, file.getName()), e); + } + } } - - getConfiguration().addGroup(args.get(0), args.subList(1, args.size())); + + + return ruleSet; } - - private void parseAcl(Integer number, List args) throws ConfigurationException + + private void parseAcl(Integer number, List args) { if (args.size() < 3) { - throw new ConfigurationException(String.format(NOT_ENOUGH_ACL_MSG, getLine())); + throw new IllegalConfigurationException(String.format(NOT_ENOUGH_ACL_MSG, getLine())); } Permission permission = Permission.parse(args.get(0)); String identity = args.get(1); Operation operation = Operation.parse(args.get(2)); - + if (number != null && !getConfiguration().isValidNumber(number)) { - throw new ConfigurationException(String.format(BAD_ACL_RULE_NUMBER_MSG, getLine())); + throw new IllegalConfigurationException(String.format(BAD_ACL_RULE_NUMBER_MSG, getLine())); } - + if (args.size() == 3) { getConfiguration().grant(number, identity, permission, operation); @@ -240,55 +255,52 @@ public class PlainConfiguration extends AbstractConfiguration else { ObjectType object = ObjectType.parse(args.get(3)); - ObjectProperties properties = toObjectProperties(args.subList(4, args.size())); + AclRulePredicates predicates = toRulePredicates(args.subList(4, args.size())); - getConfiguration().grant(number, identity, permission, operation, object, properties); + getConfiguration().grant(number, identity, permission, operation, object, predicates); } } - - private void parseConfig(List args) throws ConfigurationException + + private void parseConfig(List args) { if (args.size() < 3) { - throw new ConfigurationException(String.format(NOT_ENOUGH_CONFIG_MSG, getLine())); + throw new IllegalConfigurationException(String.format(NOT_ENOUGH_CONFIG_MSG, getLine())); } Map properties = toPluginProperties(args); - + getConfiguration().configure(properties); } - - /** Converts a {@link List} of "name", "=", "value" tokens into a {@link Map}. */ - protected ObjectProperties toObjectProperties(List args) throws ConfigurationException + + private AclRulePredicates toRulePredicates(List args) { - ObjectProperties properties = new ObjectProperties(); + AclRulePredicates predicates = new AclRulePredicates(); Iterator i = args.iterator(); while (i.hasNext()) { String key = i.next(); if (!i.hasNext()) { - throw new ConfigurationException(String.format(PROPERTY_KEY_ONLY_MSG, getLine())); + throw new IllegalConfigurationException(String.format(PROPERTY_KEY_ONLY_MSG, getLine())); } if (!"=".equals(i.next())) { - throw new ConfigurationException(String.format(PROPERTY_NO_EQUALS_MSG, getLine())); + throw new IllegalConfigurationException(String.format(PROPERTY_NO_EQUALS_MSG, getLine())); } if (!i.hasNext()) { - throw new ConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine())); + throw new IllegalConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine())); } String value = i.next(); - - // parse property key - ObjectProperties.Property property = ObjectProperties.Property.parse(key); - properties.put(property, value); + + predicates.parse(key, value); } - return properties; + return predicates; } - + /** Converts a {@link List} of "name", "=", "value" tokens into a {@link Map}. */ - protected Map toPluginProperties(List args) throws ConfigurationException + protected Map toPluginProperties(List args) { Map properties = new HashMap(); Iterator i = args.iterator(); @@ -297,24 +309,24 @@ public class PlainConfiguration extends AbstractConfiguration String key = i.next().toLowerCase(); if (!i.hasNext()) { - throw new ConfigurationException(String.format(PROPERTY_KEY_ONLY_MSG, getLine())); + throw new IllegalConfigurationException(String.format(PROPERTY_KEY_ONLY_MSG, getLine())); } if (!"=".equals(i.next())) { - throw new ConfigurationException(String.format(PROPERTY_NO_EQUALS_MSG, getLine())); + throw new IllegalConfigurationException(String.format(PROPERTY_NO_EQUALS_MSG, getLine())); } if (!i.hasNext()) { - throw new ConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine())); + throw new IllegalConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine())); } - + // parse property value and save Boolean value = Boolean.valueOf(i.next()); properties.put(key, value); } return properties; } - + protected int getLine() { return _st.lineno() - 1; diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java index 15d6b67192..cef9a8696b 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java @@ -29,7 +29,7 @@ import org.apache.qpid.server.security.access.Permission; /** * An access control v2 rule. - * + * * A rule consists of {@link Permission} for a particular identity to perform an {@link Action}. The identity * may be either a user or a group. */ @@ -37,41 +37,41 @@ public class Rule implements Comparable { /** String indicating all identitied. */ public static final String ALL = "all"; - + private Integer _number; private Boolean _enabled = Boolean.TRUE; private String _identity; - private Action _action; + private AclAction _action; private Permission _permission; - - public Rule(Integer number, String identity, Action action, Permission permission) + + public Rule(Integer number, String identity, AclAction action, Permission permission) { setNumber(number); setIdentity(identity); setAction(action); setPermission(permission); } - - public Rule(String identity, Action action, Permission permission) + + public Rule(String identity, AclAction action, Permission permission) { this(null, identity, action, permission); } - + public boolean isEnabled() { return _enabled; } - + public void setEnabled(boolean enabled) { _enabled = enabled; } - + public void enable() { _enabled = Boolean.TRUE; } - + public void disable() { _enabled = Boolean.FALSE; @@ -96,13 +96,18 @@ public class Rule implements Comparable { _identity = identity; } - + public Action getAction() + { + return _action.getAction(); + } + + public AclAction getAclAction() { return _action; } - public void setAction(Action action) + public void setAction(AclAction action) { _action = action; } @@ -117,7 +122,7 @@ public class Rule implements Comparable _permission = permission; } - /** @see Comparable#compareTo(Object) */ + @Override public int compareTo(Rule r) { return new CompareToBuilder() @@ -127,7 +132,6 @@ public class Rule implements Comparable .toComparison(); } - /** @see Object#equals(Object) */ @Override public boolean equals(Object o) { @@ -136,33 +140,31 @@ public class Rule implements Comparable return false; } Rule r = (Rule) o; - + return new EqualsBuilder() .append(getIdentity(), r.getIdentity()) - .append(getAction(), r.getAction()) + .append(getAclAction(), r.getAclAction()) .append(getPermission(), r.getPermission()) .isEquals(); } - /** @see Object#hashCode() */ @Override public int hashCode() { return new HashCodeBuilder() .append(getIdentity()) - .append(getAction()) + .append(getAclAction()) .append(getPermission()) .toHashCode(); } - /** @see Object#toString() */ @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) .append("#", getNumber()) .append("identity", getIdentity()) - .append("action", getAction()) + .append("action", getAclAction()) .append("permission", getPermission()) .append("enabled", isEnabled()) .toString(); diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java index 815df99f80..e61370fced 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java @@ -18,8 +18,8 @@ */ package org.apache.qpid.server.security.access.config; +import java.net.InetAddress; import java.security.Principal; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumMap; @@ -54,7 +54,7 @@ import org.apache.qpid.server.security.access.logging.AccessControlMessages; */ public class RuleSet { - public static final Logger _logger = Logger.getLogger(RuleSet.class); + private static final Logger _logger = Logger.getLogger(RuleSet.class); private static final String AT = "@"; private static final String SLASH = "/"; @@ -66,7 +66,6 @@ public class RuleSet private static final Integer _increment = 10; - private final Map> _aclGroups = new HashMap>(); private final SortedMap _rules = new TreeMap(); private final Map>>> _cache = new WeakHashMap>>>(); @@ -79,14 +78,13 @@ public class RuleSet } /** - * Clear the contents, including acl groups, rules and configuration. + * Clear the contents, including acl rules and configuration. */ public void clear() { _rules.clear(); _cache.clear(); _config.clear(); - _aclGroups.clear(); } public int getRuleCount() @@ -157,21 +155,27 @@ public class RuleSet public void grant(Integer number, String identity, Permission permission, Operation operation) { - Action action = new Action(operation); + AclAction action = new AclAction(operation); addRule(number, identity, permission, action); } public void grant(Integer number, String identity, Permission permission, Operation operation, ObjectType object, ObjectProperties properties) { - Action action = new Action(operation, object, properties); + AclAction action = new AclAction(operation, object, properties); addRule(number, identity, permission, action); } - public boolean ruleExists(String identity, Action action) + public void grant(Integer number, String identity, Permission permission, Operation operation, ObjectType object, AclRulePredicates predicates) + { + AclAction aclAction = new AclAction(operation, object, predicates); + addRule(number, identity, permission, aclAction); + } + + public boolean ruleExists(String identity, AclAction action) { for (Rule rule : _rules.values()) { - if (rule.getIdentity().equals(identity) && rule.getAction().equals(action)) + if (rule.getIdentity().equals(identity) && rule.getAclAction().equals(action)) { return true; } @@ -179,8 +183,7 @@ public class RuleSet return false; } - // TODO make this work when group membership is not known at file parse time - public void addRule(Integer number, String identity, Permission permission, Action action) + public void addRule(Integer number, String identity, Permission permission, AclAction action) { _cache.clear(); @@ -222,53 +225,6 @@ public class RuleSet _rules.get(Integer.valueOf(ruleNumber)).disable(); } - public boolean addGroup(String group, List constituents) - { - _cache.clear(); - - if (_aclGroups.containsKey(group)) - { - // cannot redefine - return false; - } - else - { - _aclGroups.put(group, new ArrayList()); - } - - for (String name : constituents) - { - if (name.equalsIgnoreCase(group)) - { - // recursive definition - return false; - } - - if (!checkName(name)) - { - // invalid name - return false; - } - - if (_aclGroups.containsKey(name)) - { - // is a group - _aclGroups.get(group).addAll(_aclGroups.get(name)); - } - else - { - // is a user - if (!isvalidUserName(name)) - { - // invalid username - return false; - } - _aclGroups.get(group).add(name); - } - } - return true; - } - /** Return true if the name is well-formed (contains legal characters). */ protected boolean checkName(String name) { @@ -312,11 +268,15 @@ public class RuleSet return true; } - // CPP broker authorise function prototype - // virtual bool authorise(const std::string& id, const Action& action, const ObjectType& objType, - // const std::string& name, std::map* params=0) - - // Possibly add a String name paramater? + /** + * Checks for the case when the client's address is not known. + * + * @see #check(Subject, Operation, ObjectType, ObjectProperties, InetAddress) + */ + public Result check(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties) + { + return check(subject, operation, objectType, properties, null); + } /** * Check the authorisation granted to a particular identity for an operation on an object type with @@ -327,10 +287,9 @@ public class RuleSet * the first match found, or denies access if there are no matching rules. Normally, it would be expected * to have a default deny or allow rule at the end of an access configuration however. */ - public Result check(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties) + public Result check(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties, InetAddress addressOfClient) { - // Create the action to check - Action action = new Action(operation, objectType, properties); + ClientAction action = new ClientAction(operation, objectType, properties); if(_logger.isDebugEnabled()) { @@ -349,27 +308,31 @@ public class RuleSet } // Iterate through a filtered set of rules dealing with this identity and operation - for (Rule current : rules) + for (Rule rule : rules) { if(_logger.isDebugEnabled()) { - _logger.debug("Checking against rule: " + current); + _logger.debug("Checking against rule: " + rule); } - // Check if action matches - if (action.matches(current.getAction())) + + if (action.matches(rule.getAclAction(), addressOfClient)) { - Permission permission = current.getPermission(); + Permission permission = rule.getPermission(); switch (permission) { case ALLOW_LOG: CurrentActor.get().message(AccessControlMessages.ALLOWED( - action.getOperation().toString(), action.getObjectType().toString(), action.getProperties().toString())); + action.getOperation().toString(), + action.getObjectType().toString(), + action.getProperties().toString())); case ALLOW: return Result.ALLOWED; case DENY_LOG: CurrentActor.get().message(AccessControlMessages.DENIED( - action.getOperation().toString(), action.getObjectType().toString(), action.getProperties().toString())); + action.getOperation().toString(), + action.getObjectType().toString(), + action.getProperties().toString())); case DENY: return Result.DENIED; } @@ -446,8 +409,7 @@ public class RuleSet { final Principal principal = iterator.next(); - if (rule.getIdentity().equalsIgnoreCase(principal.getName()) - || (_aclGroups.containsKey(rule.getIdentity()) && _aclGroups.get(rule.getIdentity()).contains(principal.getName()))) + if (rule.getIdentity().equalsIgnoreCase(principal.getName())) { return true; } @@ -476,5 +438,4 @@ public class RuleSet } return objects; } - } diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AccessControlFirewallException.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AccessControlFirewallException.java new file mode 100644 index 0000000000..d08a052efd --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AccessControlFirewallException.java @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.access.firewall; + +public class AccessControlFirewallException extends RuntimeException +{ + /** serialVersionUID */ + private static final long serialVersionUID = 4526157149690917805L; + + public AccessControlFirewallException() + { + super(); + } + + public AccessControlFirewallException(String message) + { + super(message); + } + + public AccessControlFirewallException(String message, Throwable cause) + { + super(message, cause); + } + + public AccessControlFirewallException(Throwable cause) + { + super(cause); + } +} \ No newline at end of file diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRule.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRule.java new file mode 100644 index 0000000000..482a795693 --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRule.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.access.firewall; + +import java.net.InetAddress; + +public interface FirewallRule +{ + boolean matches(InetAddress addressOfClient); +} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRuleFactory.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRuleFactory.java new file mode 100644 index 0000000000..64be26c209 --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/FirewallRuleFactory.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.access.firewall; + +public class FirewallRuleFactory +{ + public FirewallRule createForHostname(String[] hostnames) + { + return new HostnameFirewallRule(hostnames); + } + + public FirewallRule createForNetwork(String[] networks) + { + return new NetworkFirewallRule(networks); + } + +} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRule.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRule.java new file mode 100644 index 0000000000..fb13426fbb --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRule.java @@ -0,0 +1,156 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.firewall; + +import java.net.InetAddress; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.log4j.Logger; + +public class HostnameFirewallRule implements FirewallRule +{ + private static final Logger _logger = Logger.getLogger(HostnameFirewallRule.class); + + private static final long DNS_TIMEOUT = 30000; + private static final ExecutorService DNS_LOOKUP = Executors.newCachedThreadPool(); + + private Pattern[] _hostnamePatterns; + private String[] _hostnames; + + public HostnameFirewallRule(String... hostnames) + { + _hostnames = hostnames; + + int i = 0; + _hostnamePatterns = new Pattern[hostnames.length]; + for (String hostname : hostnames) + { + _hostnamePatterns[i++] = Pattern.compile(hostname); + } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Created " + this); + } + } + + @Override + public boolean matches(InetAddress remote) + { + String hostname = getHostname(remote); + if (hostname == null) + { + throw new AccessControlFirewallException("DNS lookup failed for address " + remote); + } + for (Pattern pattern : _hostnamePatterns) + { + boolean hostnameMatches = pattern.matcher(hostname).matches(); + + if (hostnameMatches) + { + if(_logger.isDebugEnabled()) + { + _logger.debug("Hostname " + hostname + " matches rule " + pattern.toString()); + } + return true; + } + } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Hostname " + hostname + " matches no configured hostname patterns"); + } + + return false; + } + + + /** + * @param remote + * the InetAddress to look up + * @return the hostname, null if not found, takes longer than + * {@value #DNS_LOOKUP} to find or otherwise fails + */ + private String getHostname(final InetAddress remote) throws AccessControlFirewallException + { + FutureTask lookup = new FutureTask(new Callable() + { + public String call() + { + return remote.getCanonicalHostName(); + } + }); + DNS_LOOKUP.execute(lookup); + + try + { + return lookup.get(DNS_TIMEOUT, TimeUnit.MILLISECONDS); + } + catch (Exception e) + { + _logger.warn("Unable to look up hostname from address " + remote, e); + return null; + } + finally + { + lookup.cancel(true); + } + } + + @Override + public int hashCode() + { + return new HashCodeBuilder().append(_hostnames).toHashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (obj == this) + { + return true; + } + if (obj.getClass() != getClass()) + { + return false; + } + HostnameFirewallRule rhs = (HostnameFirewallRule) obj; + return new EqualsBuilder().append(_hostnames, rhs._hostnames).isEquals(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append(_hostnames).toString(); + } +} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/InetNetwork.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/InetNetwork.java new file mode 100644 index 0000000000..2e979b38f1 --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/InetNetwork.java @@ -0,0 +1,177 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.access.firewall; + +import java.net.InetAddress; + +class InetNetwork +{ + /* + * Implements network masking, and is compatible with RFC 1518 and + * RFC 1519, which describe CIDR: Classless Inter-Domain Routing. + */ + + private InetAddress network; + private InetAddress netmask; + + public InetNetwork(InetAddress ip, InetAddress netmask) + { + this.network = maskIP(ip, netmask); + this.netmask = netmask; + } + + public boolean contains(final String name) throws java.net.UnknownHostException + { + return network.equals(maskIP(InetAddress.getByName(name), netmask)); + } + + public boolean contains(final InetAddress ip) + { + return network.equals(maskIP(ip, netmask)); + } + + @Override + public String toString() + { + return network.getHostAddress() + "/" + netmask.getHostAddress(); + } + + @Override + public int hashCode() + { + return maskIP(network, netmask).hashCode(); + } + + @Override + public boolean equals(Object obj) + { + return (obj != null) && + (obj instanceof InetNetwork) && + ((InetNetwork)obj).network.equals(network) && + ((InetNetwork)obj).netmask.equals(netmask); + } + + public static InetNetwork getFromString(String netspec) throws java.net.UnknownHostException + { + if (netspec.endsWith("*")) + { + netspec = normalizeFromAsterisk(netspec); + } + else + { + int iSlash = netspec.indexOf('/'); + if (iSlash == -1) + { + netspec += "/255.255.255.255"; + } + else if (netspec.indexOf('.', iSlash) == -1) + { + netspec = normalizeFromCIDR(netspec); + } + } + + return new InetNetwork( + InetAddress.getByName(netspec.substring(0, netspec.indexOf('/'))), + InetAddress.getByName(netspec.substring(netspec.indexOf('/') + 1))); + } + + public static InetAddress maskIP(final byte[] ip, final byte[] mask) + { + try + { + return getByAddress( + new byte[] + { + (byte) (mask[0] & ip[0]), + (byte) (mask[1] & ip[1]), + (byte) (mask[2] & ip[2]), + (byte) (mask[3] & ip[3]) + } + ); + } + catch (Exception _) + { + return null; + } + } + + public static InetAddress maskIP(final InetAddress ip, final InetAddress mask) + { + return maskIP(ip.getAddress(), mask.getAddress()); + } + + /* + * This converts from an uncommon "wildcard" CIDR format + * to "address + mask" format: + * + * * => 000.000.000.0/000.000.000.0 + * xxx.* => xxx.000.000.0/255.000.000.0 + * xxx.xxx.* => xxx.xxx.000.0/255.255.000.0 + * xxx.xxx.xxx.* => xxx.xxx.xxx.0/255.255.255.0 + */ + static private String normalizeFromAsterisk(final String netspec) + { + String[] masks = { "0.0.0.0/0.0.0.0", "0.0.0/255.0.0.0", "0.0/255.255.0.0", "0/255.255.255.0" }; + char[] srcb = netspec.toCharArray(); + int octets = 0; + for (int i = 1; i < netspec.length(); i++) + { + if (srcb[i] == '.') + { + octets++; + } + } + return (octets == 0) ? masks[0] : netspec.substring(0, netspec.length() -1 ).concat(masks[octets]); + } + + /* + * RFC 1518, 1519 - Classless Inter-Domain Routing (CIDR) + * This converts from "prefix + prefix-length" format to + * "address + mask" format, e.g. from xxx.xxx.xxx.xxx/yy + * to xxx.xxx.xxx.xxx/yyy.yyy.yyy.yyy. + */ + static private String normalizeFromCIDR(final String netspec) + { + final int bits = 32 - Integer.parseInt(netspec.substring(netspec.indexOf('/')+1)); + final int mask = (bits == 32) ? 0 : 0xFFFFFFFF - ((1 << bits)-1); + + return netspec.substring(0, netspec.indexOf('/') + 1) + + Integer.toString(mask >> 24 & 0xFF, 10) + "." + + Integer.toString(mask >> 16 & 0xFF, 10) + "." + + Integer.toString(mask >> 8 & 0xFF, 10) + "." + + Integer.toString(mask >> 0 & 0xFF, 10); + } + + private static InetAddress getByAddress(byte[] ip) throws java.net.UnknownHostException + { + InetAddress addr = InetAddress.getByAddress(ip); + + if (addr == null) { + addr = InetAddress.getByName + ( + Integer.toString(ip[0] & 0xFF, 10) + "." + + Integer.toString(ip[1] & 0xFF, 10) + "." + + Integer.toString(ip[2] & 0xFF, 10) + "." + + Integer.toString(ip[3] & 0xFF, 10) + ); + } + + return addr; + } +} \ No newline at end of file diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRule.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRule.java new file mode 100644 index 0000000000..ad619a0e0b --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRule.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.firewall; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.log4j.Logger; + +public class NetworkFirewallRule implements FirewallRule +{ + private static final Logger _logger = Logger.getLogger(NetworkFirewallRule.class); + + private List _networks; + + public NetworkFirewallRule(String... networks) + { + _networks = new ArrayList(); + for (int i = 0; i < networks.length; i++) + { + String network = networks[i]; + try + { + InetNetwork inetNetwork = InetNetwork.getFromString(network); + if (!_networks.contains(inetNetwork)) + { + _networks.add(inetNetwork); + } + } + catch (java.net.UnknownHostException uhe) + { + _logger.error("Cannot resolve address: " + network, uhe); + } + } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Created " + this); + } + } + + @Override + public boolean matches(InetAddress ip) + { + for (InetNetwork network : _networks) + { + if (network.contains(ip)) + { + if(_logger.isDebugEnabled()) + { + _logger.debug("Client address " + ip + " matches configured network " + network); + } + return true; + } + } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Client address " + ip + " does not match any configured networks"); + } + + return false; + } + + @Override + public int hashCode() + { + return new HashCodeBuilder().append(_networks).toHashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (obj == this) + { + return true; + } + if (obj.getClass() != getClass()) + { + return false; + } + NetworkFirewallRule rhs = (NetworkFirewallRule) obj; + return new EqualsBuilder().append(_networks, rhs._networks).isEquals(); + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append(_networks).toString(); + } +} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/logging/AccessControl_logmessages.properties b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/logging/AccessControl_logmessages.properties index bf80df3722..2a5eb7b3be 100644 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/logging/AccessControl_logmessages.properties +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/logging/AccessControl_logmessages.properties @@ -25,4 +25,4 @@ ALLOWED = ACL-1001 : Allowed : {0} {1} {2} # 'deny-log' rule message -DENIED = ACL-1002 : Denied : {0} {1} {2} \ No newline at end of file +DENIED = ACL-1002 : Denied : {0} {1} {2} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java deleted file mode 100644 index d8a5bd4085..0000000000 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.security.access.plugins; - -import javax.security.auth.Subject; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.security.AbstractPlugin; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.SecurityPluginFactory; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; -import org.apache.qpid.server.security.access.config.RuleSet; - -/** - * This access control plugin implements version two plain text access control. - */ -public class AccessControl extends AbstractPlugin -{ - public static final Logger _logger = Logger.getLogger(AccessControl.class); - - private RuleSet _ruleSet; - - public static final SecurityPluginFactory FACTORY = new SecurityPluginFactory() - { - public Class getPluginClass() - { - return AccessControl.class; - } - - public String getPluginName() - { - return AccessControl.class.getName(); - } - - public AccessControl newInstance(ConfigurationPlugin config) throws ConfigurationException - { - AccessControlConfiguration configuration = config.getConfiguration(AccessControlConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - return null; - } - - AccessControl plugin = new AccessControl(); - plugin.configure(configuration); - return plugin; - } - }; - - public Result getDefault() - { - return _ruleSet.getDefault(); - } - - /** - * Object instance access authorisation. - * - * Delegate to the {@link #authorise(Operation, ObjectType, ObjectProperties)} method, with - * the operation set to ACCESS and no object properties. - */ - public Result access(ObjectType objectType, Object instance) - { - return authorise(Operation.ACCESS, objectType, ObjectProperties.EMPTY); - } - - /** - * Check if an operation is authorised by asking the configuration object about the access - * control rules granted to the current thread's {@link Subject}. If there is no current - * user the plugin will abstain. - */ - public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) - { - final Subject subject = SecurityManager.getThreadSubject(); - // Abstain if there is no subject/principal associated with this thread - if (subject == null || subject.getPrincipals().size() == 0) - { - return Result.ABSTAIN; - } - - _logger.debug("Checking " + operation + " " + objectType); - return _ruleSet.check(subject, operation, objectType, properties); - } - - public void configure(ConfigurationPlugin config) - { - super.configure(config); - - AccessControlConfiguration accessConfig = (AccessControlConfiguration) getConfig(); - - _ruleSet = accessConfig.getRuleSet(); - } -} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java deleted file mode 100644 index 7c83446cf1..0000000000 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.security.access.plugins; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.security.SecurityPluginActivator; -import org.apache.qpid.server.security.SecurityPluginFactory; - -/** - * The OSGi {@link org.osgi.framework.BundleActivator} for {@link AccessControl}. - */ -public class AccessControlActivator extends SecurityPluginActivator -{ - public SecurityPluginFactory getFactory() - { - return AccessControl.FACTORY; - } - - public ConfigurationPluginFactory getConfigurationFactory() - { - return AccessControlConfiguration.FACTORY; - } -} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java deleted file mode 100644 index c4db6db820..0000000000 --- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.security.access.plugins; - -import java.io.File; -import java.util.Arrays; -import java.util.List; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.security.access.config.ConfigurationFile; -import org.apache.qpid.server.security.access.config.PlainConfiguration; -import org.apache.qpid.server.security.access.config.RuleSet; - -public class AccessControlConfiguration extends ConfigurationPlugin -{ - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - ConfigurationPlugin instance = new AccessControlConfiguration(); - instance.setConfiguration(path, config); - return instance; - } - - public List getParentPaths() - { - return Arrays.asList("security.acl", "virtualhosts.virtualhost.security.acl"); - } - }; - - private RuleSet _ruleSet; - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - - public String getFileName() - { - return getConfig().getString(""); - } - - public void validateConfiguration() throws ConfigurationException - { - String filename = getFileName(); - if (filename == null) - { - throw new ConfigurationException("No ACL file name specified"); - } - - File aclFile = new File(filename); - - ConfigurationFile configFile = new PlainConfiguration(aclFile); - _ruleSet = configFile.load(); - } - - public RuleSet getRuleSet() - { - return _ruleSet; - } - -} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java new file mode 100644 index 0000000000..6f7885da94 --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java @@ -0,0 +1,122 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.plugins; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.io.File; + +import javax.security.auth.Subject; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.lang.ObjectUtils; +import org.apache.log4j.Logger; +import org.apache.qpid.server.security.Result; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.AccessControl; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.access.config.ConfigurationFile; +import org.apache.qpid.server.security.access.config.PlainConfiguration; +import org.apache.qpid.server.security.access.config.RuleSet; + +public class DefaultAccessControl implements AccessControl +{ + private static final Logger _logger = Logger.getLogger(DefaultAccessControl.class); + + private RuleSet _ruleSet; + + public DefaultAccessControl(String fileName) + { + if (_logger.isDebugEnabled()) + { + _logger.debug("Creating AccessControl instance using file: " + fileName); + } + File aclFile = new File(fileName); + + ConfigurationFile configFile = new PlainConfiguration(aclFile); + _ruleSet = configFile.load(); + } + + DefaultAccessControl(RuleSet rs) throws ConfigurationException + { + _ruleSet = rs; + } + + public Result getDefault() + { + return _ruleSet.getDefault(); + } + + /** + * Object instance access authorisation. + * + * Delegate to the {@link #authorise(Operation, ObjectType, ObjectProperties)} method, with + * the operation set to ACCESS and no object properties. + */ + public Result access(ObjectType objectType, Object inetSocketAddress) + { + InetAddress addressOfClient = null; + + if(inetSocketAddress != null) + { + addressOfClient = ((InetSocketAddress) inetSocketAddress).getAddress(); + } + + return authoriseFromAddress(Operation.ACCESS, objectType, ObjectProperties.EMPTY, addressOfClient); + } + + /** + * Check if an operation is authorised by asking the configuration object about the access + * control rules granted to the current thread's {@link Subject}. If there is no current + * user the plugin will abstain. + */ + public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) + { + return authoriseFromAddress(operation, objectType, properties, null); + } + + public Result authoriseFromAddress(Operation operation, ObjectType objectType, ObjectProperties properties, InetAddress addressOfClient) + { + final Subject subject = SecurityManager.getThreadSubject(); + // Abstain if there is no subject/principal associated with this thread + if (subject == null || subject.getPrincipals().size() == 0) + { + return Result.ABSTAIN; + } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Checking " + operation + " " + objectType + " " + ObjectUtils.defaultIfNull(addressOfClient, "")); + } + + try + { + return _ruleSet.check(subject, operation, objectType, properties, addressOfClient); + } + catch(Exception e) + { + _logger.error("Unable to check " + operation + " " + objectType + " " + ObjectUtils.defaultIfNull(addressOfClient, ""), e); + return Result.DENIED; + } + } +} diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java new file mode 100644 index 0000000000..a3d7823caf --- /dev/null +++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java @@ -0,0 +1,59 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.access.plugins; + +import java.io.File; +import java.util.Map; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.plugin.AccessControlFactory; +import org.apache.qpid.server.security.AccessControl; + +public class DefaultAccessControlFactory implements AccessControlFactory +{ + public static final String ATTRIBUTE_ACL_FILE = "aclFile"; + + public AccessControl createInstance(Map aclConfiguration) + { + if (aclConfiguration != null) + { + Object aclFile = aclConfiguration.get(ATTRIBUTE_ACL_FILE); + if (aclFile != null) + { + if (aclFile instanceof String) + { + String aclPath = (String) aclFile; + if (!new File(aclPath).exists()) + { + throw new IllegalConfigurationException("ACL file '" + aclPath + "' is not found"); + } + return new DefaultAccessControl(aclPath); + } + else + { + throw new IllegalConfigurationException("Expected '" + ATTRIBUTE_ACL_FILE + "' attribute value of type String but was " + aclFile.getClass() + + ": " + aclFile); + } + } + } + return null; + } +} diff --git a/java/broker-plugins/access-control/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AccessControlFactory b/java/broker-plugins/access-control/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AccessControlFactory new file mode 100644 index 0000000000..b6c429baab --- /dev/null +++ b/java/broker-plugins/access-control/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AccessControlFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.security.access.plugins.DefaultAccessControlFactory diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclActionTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclActionTest.java new file mode 100644 index 0000000000..14620cff70 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclActionTest.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.access.config; + +import static org.mockito.Mockito.*; + +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.access.firewall.FirewallRule; + +import junit.framework.TestCase; + +public class AclActionTest extends TestCase +{ + public void testEqualsAndHashCode() + { + AclRulePredicates predicates = createAclRulePredicates(); + ObjectType objectType = ObjectType.EXCHANGE; + Operation operation = Operation.ACCESS; + + AclAction aclAction = new AclAction(operation, objectType, predicates); + AclAction equalAclAction = new AclAction(operation, objectType, predicates); + + assertTrue(aclAction.equals(aclAction)); + assertTrue(aclAction.equals(equalAclAction)); + assertTrue(equalAclAction.equals(aclAction)); + + assertTrue(aclAction.hashCode() == equalAclAction.hashCode()); + + assertFalse("Different operation should cause aclActions to be unequal", + aclAction.equals(new AclAction(Operation.BIND, objectType, predicates))); + + assertFalse("Different operation type should cause aclActions to be unequal", + aclAction.equals(new AclAction(operation, ObjectType.GROUP, predicates))); + + assertFalse("Different predicates should cause aclActions to be unequal", + aclAction.equals(new AclAction(operation, objectType, createAclRulePredicates()))); + + } + + private AclRulePredicates createAclRulePredicates() + { + AclRulePredicates predicates = mock(AclRulePredicates.class); + when(predicates.getFirewallRule()).thenReturn(mock(FirewallRule.class)); + when(predicates.getObjectProperties()).thenReturn(mock(ObjectProperties.class)); + return predicates; + } + +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclRulePredicatesTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclRulePredicatesTest.java new file mode 100644 index 0000000000..93b765d0fb --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclRulePredicatesTest.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.config; + +import static org.apache.qpid.server.security.access.ObjectProperties.Property.*; + +import org.apache.qpid.server.security.access.firewall.FirewallRule; +import org.apache.qpid.server.security.access.firewall.FirewallRuleFactory; + +import static org.mockito.Mockito.*; + +import junit.framework.TestCase; + +public class AclRulePredicatesTest extends TestCase +{ + private AclRulePredicates _aclRulePredicates = new AclRulePredicates(); + private FirewallRuleFactory _firewallRuleFactory = mock(FirewallRuleFactory.class); + + @Override + protected void setUp() throws Exception + { + _aclRulePredicates.setFirewallRuleFactory(_firewallRuleFactory); + + when(_firewallRuleFactory.createForHostname((String[]) any())).thenReturn(mock(FirewallRule.class)); + when(_firewallRuleFactory.createForNetwork((String[]) any())).thenReturn(mock(FirewallRule.class)); + } + + public void testParse() + { + String name = "name"; + String className = "class"; + + _aclRulePredicates.parse(NAME.name(), name); + _aclRulePredicates.parse(CLASS.name(), className); + + assertEquals(name, _aclRulePredicates.getObjectProperties().get(NAME)); + assertEquals(className, _aclRulePredicates.getObjectProperties().get(CLASS)); + } + + public void testParseHostnameFirewallRule() + { + String hostname = "hostname1,hostname2"; + _aclRulePredicates.parse(FROM_HOSTNAME.name(), hostname); + + verify(_firewallRuleFactory).createForHostname(new String[] {"hostname1", "hostname2"}); + } + + public void testParseNetworkFirewallRule() + { + _aclRulePredicates.setFirewallRuleFactory(_firewallRuleFactory); + + String networks = "network1,network2"; + _aclRulePredicates.parse(FROM_NETWORK.name(), networks); + + verify(_firewallRuleFactory).createForNetwork(new String[] {"network1", "network2"}); + } + + public void testParseThrowsExceptionIfBothHostnameAndNetworkSpecified() + { + _aclRulePredicates.parse(FROM_NETWORK.name(), "network1,network2"); + try + { + _aclRulePredicates.parse(FROM_HOSTNAME.name(), "hostname1,hostname2"); + fail("Exception not thrown"); + } + catch(IllegalStateException e) + { + // pass + } + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java new file mode 100644 index 0000000000..00e06106bf --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.access.config; + +import static org.mockito.Mockito.*; + +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; + +import junit.framework.TestCase; + +public class ActionTest extends TestCase +{ + private ObjectProperties _properties1 = mock(ObjectProperties.class); + private ObjectProperties _properties2 = mock(ObjectProperties.class); + + public void testMatchesReturnsTrueForMatchingActions() + { + when(_properties1.matches(_properties2)).thenReturn(true); + + assertMatches( + new Action(Operation.CONSUME, ObjectType.QUEUE, _properties1), + new Action(Operation.CONSUME, ObjectType.QUEUE, _properties2)); + } + + public void testMatchesReturnsFalseWhenOperationsDiffer() + { + assertDoesntMatch( + new Action(Operation.CONSUME, ObjectType.QUEUE, _properties1), + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1)); + } + + public void testMatchesReturnsFalseWhenOperationTypesDiffer() + { + assertDoesntMatch( + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1), + new Action(Operation.CREATE, ObjectType.EXCHANGE, _properties1)); + } + + public void testMatchesReturnsFalseWhenOperationPropertiesDiffer() + { + assertDoesntMatch( + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1), + new Action(Operation.CREATE, ObjectType.QUEUE, _properties2)); + } + + public void testMatchesReturnsFalseWhenMyOperationPropertiesIsNull() + { + assertDoesntMatch( + new Action(Operation.CREATE, ObjectType.QUEUE, (ObjectProperties)null), + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1)); + } + + public void testMatchesReturnsFalseWhenOtherOperationPropertiesIsNull() + { + assertDoesntMatch( + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1), + new Action(Operation.CREATE, ObjectType.QUEUE, (ObjectProperties)null)); + } + + public void testMatchesReturnsTrueWhenBothOperationPropertiesAreNull() + { + assertMatches( + new Action(Operation.CREATE, ObjectType.QUEUE, (ObjectProperties)null), + new Action(Operation.CREATE, ObjectType.QUEUE, (ObjectProperties)null)); + } + + private void assertMatches(Action action1, Action action2) + { + assertTrue(action1 + " should match " + action2, action1.matches(action2)); + } + + private void assertDoesntMatch(Action action1, Action action2) + { + assertFalse(action1 + " should not match " + action2, action1.matches(action2)); + } + +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ClientActionTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ClientActionTest.java new file mode 100644 index 0000000000..ae5d3fda74 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ClientActionTest.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.config; + +import static org.mockito.Mockito.*; + +import java.net.InetAddress; + +import org.apache.qpid.server.security.access.firewall.FirewallRule; + +import junit.framework.TestCase; + +public class ClientActionTest extends TestCase +{ + private Action _action = mock(Action.class); + private AclAction _ruleAction = mock(AclAction.class); + private InetAddress _addressOfClient = mock(InetAddress.class); + + private ClientAction _clientAction = new ClientAction(_action); + + public void testMatches_returnsTrueWhenActionsMatchAndNoFirewallRule() + { + when(_action.matches(any(Action.class))).thenReturn(true); + when(_ruleAction.getFirewallRule()).thenReturn(null); + + assertTrue(_clientAction.matches(_ruleAction, _addressOfClient)); + } + + public void testMatches_returnsFalseWhenActionsDontMatch() + { + FirewallRule firewallRule = mock(FirewallRule.class); + when(firewallRule.matches(_addressOfClient)).thenReturn(true); + + when(_action.matches(any(Action.class))).thenReturn(false); + when(_ruleAction.getFirewallRule()).thenReturn(firewallRule); + + assertFalse(_clientAction.matches(_ruleAction, _addressOfClient)); + } + + public void testMatches_returnsTrueWhenActionsAndFirewallRuleMatch() + { + FirewallRule firewallRule = mock(FirewallRule.class); + when(firewallRule.matches(_addressOfClient)).thenReturn(true); + + when(_action.matches(any(Action.class))).thenReturn(true); + when(_ruleAction.getFirewallRule()).thenReturn(firewallRule); + + assertTrue(_clientAction.matches(_ruleAction, _addressOfClient)); + } + + public void testMatches_ignoresFirewallRuleIfClientAddressIsNull() + { + FirewallRule firewallRule = mock(FirewallRule.class); + + when(_action.matches(any(Action.class))).thenReturn(true); + when(_ruleAction.getFirewallRule()).thenReturn(firewallRule); + + assertTrue(_clientAction.matches(_ruleAction, null)); + + verifyZeroInteractions(firewallRule); + } + +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java new file mode 100644 index 0000000000..cbfc9003c8 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java @@ -0,0 +1,463 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.config; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectProperties.Property; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.access.config.ConfigurationFile; +import org.apache.qpid.server.security.access.config.PlainConfiguration; +import org.apache.qpid.server.security.access.config.Rule; +import org.apache.qpid.server.security.access.config.RuleSet; + +/** + * These tests check that the ACL file parsing works correctly. + * + * For each message that can be returned in a {@link ConfigurationException}, an ACL file is created that should trigger this + * particular message. + */ +public class PlainConfigurationTest extends TestCase +{ + private PlainConfiguration writeACLConfig(String...aclData) throws Exception + { + File acl = File.createTempFile(getClass().getName() + getName(), "acl"); + acl.deleteOnExit(); + + // Write ACL file + PrintWriter aclWriter = new PrintWriter(new FileWriter(acl)); + for (String line : aclData) + { + aclWriter.println(line); + } + aclWriter.close(); + + // Load ruleset + PlainConfiguration configFile = new PlainConfiguration(acl); + configFile.load(); + return configFile; + } + + public void testMissingACLConfig() throws Exception + { + try + { + // Load ruleset + ConfigurationFile configFile = new PlainConfiguration(new File("doesnotexist")); + configFile.load(); + + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.CONFIG_NOT_FOUND_MSG, "doesnotexist"), ce.getMessage()); + assertTrue(ce.getCause() instanceof FileNotFoundException); + } + } + + public void testACLFileSyntaxContinuation() throws Exception + { + try + { + writeACLConfig("ACL ALLOW ALL \\ ALL"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PREMATURE_CONTINUATION_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxTokens() throws Exception + { + try + { + writeACLConfig("ACL unparsed ALL ALL"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PARSE_TOKEN_FAILED_MSG, 1), ce.getMessage()); + assertTrue(ce.getCause() instanceof IllegalArgumentException); + assertEquals("Not a valid permission: unparsed", ce.getCause().getMessage()); + } + } + + public void testACLFileSyntaxNotEnoughACL() throws Exception + { + try + { + writeACLConfig("ACL ALLOW"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_ACL_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxNotEnoughConfig() throws Exception + { + try + { + writeACLConfig("CONFIG"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxNotEnough() throws Exception + { + try + { + writeACLConfig("INVALID"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxPropertyKeyOnly() throws Exception + { + try + { + writeACLConfig("ACL ALLOW adk CREATE QUEUE name"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PROPERTY_KEY_ONLY_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxPropertyNoEquals() throws Exception + { + try + { + writeACLConfig("ACL ALLOW adk CREATE QUEUE name test"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PROPERTY_NO_EQUALS_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxPropertyNoValue() throws Exception + { + try + { + writeACLConfig("ACL ALLOW adk CREATE QUEUE name ="); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PROPERTY_NO_VALUE_MSG, 1), ce.getMessage()); + } + } + + /** + * Tests interpretation of an acl rule with no object properties. + * + */ + public void testValidRule() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL DENY-LOG user1 ACCESS VIRTUALHOST"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); + assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule with object properties quoted in single quotes. + */ + public void testValidRuleWithSingleQuotedProperty() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE name = \'value\'"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "all", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.CREATE, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); + final ObjectProperties expectedProperties = new ObjectProperties(); + expectedProperties.setName("value"); + assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule with object properties quoted in double quotes. + */ + public void testValidRuleWithDoubleQuotedProperty() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE name = \"value\""); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "all", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.CREATE, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); + final ObjectProperties expectedProperties = new ObjectProperties(); + expectedProperties.setName("value"); + assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule with many object properties. + */ + public void testValidRuleWithManyProperties() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL ALLOW admin DELETE QUEUE name=name1 owner = owner1"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "admin", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.DELETE, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.QUEUE, rule.getAction().getObjectType()); + final ObjectProperties expectedProperties = new ObjectProperties(); + expectedProperties.setName("name1"); + expectedProperties.put(Property.OWNER, "owner1"); + assertEquals("Rule has unexpected operation", expectedProperties, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule with object properties containing wildcards. Values containing + * hashes must be quoted otherwise they are interpreted as comments. + */ + public void testValidRuleWithWildcardProperties() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE routingKey = \'news.#\'", + "ACL ALLOW all CREATE EXCHANGE routingKey = \'news.co.#\'", + "ACL ALLOW all CREATE EXCHANGE routingKey = *.co.medellin"); + final RuleSet rs = config.getConfiguration(); + assertEquals(3, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(3, rules.size()); + final Rule rule1 = rules.get(0); + assertEquals("Rule has unexpected identity", "all", rule1.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.CREATE, rule1.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule1.getAction().getObjectType()); + final ObjectProperties expectedProperties1 = new ObjectProperties(); + expectedProperties1.put(Property.ROUTING_KEY,"news.#"); + assertEquals("Rule has unexpected object properties", expectedProperties1, rule1.getAction().getProperties()); + + final Rule rule2 = rules.get(10); + final ObjectProperties expectedProperties2 = new ObjectProperties(); + expectedProperties2.put(Property.ROUTING_KEY,"news.co.#"); + assertEquals("Rule has unexpected object properties", expectedProperties2, rule2.getAction().getProperties()); + + final Rule rule3 = rules.get(20); + final ObjectProperties expectedProperties3 = new ObjectProperties(); + expectedProperties3.put(Property.ROUTING_KEY,"*.co.medellin"); + assertEquals("Rule has unexpected object properties", expectedProperties3, rule3.getAction().getProperties()); + } + + /** + * Tests that rules are case insignificant. + */ + public void testMixedCaseRuleInterpretation() throws Exception + { + final PlainConfiguration config = writeACLConfig("AcL deny-LOG User1 BiND Exchange Name=AmQ.dIrect"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "User1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.BIND, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); + final ObjectProperties expectedProperties = new ObjectProperties("AmQ.dIrect"); + assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); + } + + /** + * Tests whitespace is supported. Note that currently the Java implementation permits comments to + * be introduced anywhere in the ACL, whereas the C++ supports only whitespace at the beginning of + * of line. + */ + public void testCommentsSuppported() throws Exception + { + final PlainConfiguration config = writeACLConfig("#Comment", + "ACL DENY-LOG user1 ACCESS VIRTUALHOST # another comment", + " # final comment with leading whitespace"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); + assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule using mixtures of tabs/spaces as token separators. + * + */ + public void testWhitespace() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL\tDENY-LOG\t\t user1\t \tACCESS VIRTUALHOST"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); + assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl utilising line continuation. + */ + public void testLineContination() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL DENY-LOG user1 \\", + "ACCESS VIRTUALHOST"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); + assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); + } + + public void testUserRuleParsing() throws Exception + { + validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER"), + "user1", Operation.CREATE, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER name=\"otherUser\""), + "user1", Operation.CREATE, ObjectType.USER, new ObjectProperties("otherUser")); + + validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER"), + "user1", Operation.DELETE, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER name=\"otherUser\""), + "user1", Operation.DELETE, ObjectType.USER, new ObjectProperties("otherUser")); + + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER"), + "user1", Operation.UPDATE, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER name=\"otherUser\""), + "user1", Operation.UPDATE, ObjectType.USER, new ObjectProperties("otherUser")); + + validateRule(writeACLConfig("ACL ALLOW user1 ALL USER"), + "user1", Operation.ALL, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 ALL USER name=\"otherUser\""), + "user1", Operation.ALL, ObjectType.USER, new ObjectProperties("otherUser")); + } + + public void testGroupRuleParsing() throws Exception + { + validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP"), + "user1", Operation.CREATE, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP name=\"groupName\""), + "user1", Operation.CREATE, ObjectType.GROUP, new ObjectProperties("groupName")); + + validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP"), + "user1", Operation.DELETE, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP name=\"groupName\""), + "user1", Operation.DELETE, ObjectType.GROUP, new ObjectProperties("groupName")); + + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP"), + "user1", Operation.UPDATE, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP name=\"groupName\""), + "user1", Operation.UPDATE, ObjectType.GROUP, new ObjectProperties("groupName")); + + validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP"), + "user1", Operation.ALL, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP name=\"groupName\""), + "user1", Operation.ALL, ObjectType.GROUP, new ObjectProperties("groupName")); + } + + /** explicitly test for exception indicating that this functionality has been moved to Group Providers */ + public void testGroupDefinitionThrowsException() throws Exception + { + try + { + writeACLConfig("GROUP group1 bob alice"); + fail("Expected exception not thrown"); + } + catch(IllegalConfigurationException e) + { + assertTrue(e.getMessage().contains("GROUP keyword not supported")); + } + } + + public void testManagementRuleParsing() throws Exception + { + validateRule(writeACLConfig("ACL ALLOW user1 ALL MANAGEMENT"), + "user1", Operation.ALL, ObjectType.MANAGEMENT, ObjectProperties.EMPTY); + + validateRule(writeACLConfig("ACL ALLOW user1 ACCESS MANAGEMENT"), + "user1", Operation.ACCESS, ObjectType.MANAGEMENT, ObjectProperties.EMPTY); + } + + private void validateRule(final PlainConfiguration config, String username, Operation operation, ObjectType objectType, ObjectProperties objectProperties) + { + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", username, rule.getIdentity()); + assertEquals("Rule has unexpected operation", operation, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", objectType, rule.getAction().getObjectType()); + assertEquals("Rule has unexpected object properties", objectProperties, rule.getAction().getProperties()); + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/RuleTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/RuleTest.java new file mode 100644 index 0000000000..2ae7759679 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/RuleTest.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.access.config; + +import static org.mockito.Mockito.*; + +import org.apache.qpid.server.security.access.Permission; + +import junit.framework.TestCase; + +public class RuleTest extends TestCase +{ + public void testEqualsAndHashCode() + { + AclAction aclAction = mock(AclAction.class); + String identity = "identity"; + Permission allow = Permission.ALLOW; + + Rule rule = new Rule(identity, aclAction, allow); + Rule equalRule = new Rule(identity, aclAction, allow); + + assertTrue(rule.equals(rule)); + assertTrue(rule.equals(equalRule)); + assertTrue(equalRule.equals(rule)); + + assertTrue(rule.hashCode() == equalRule.hashCode()); + + assertFalse("Different identity should cause rules to be unequal", + rule.equals(new Rule("identity2", aclAction, allow))); + + assertFalse("Different action should cause rules to be unequal", + rule.equals(new Rule(identity, mock(AclAction.class), allow))); + + assertFalse("Different permission should cause rules to be unequal", + rule.equals(new Rule(identity, aclAction, Permission.DENY))); + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRuleTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRuleTest.java new file mode 100644 index 0000000000..be82cb294a --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRuleTest.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.firewall; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.InetAddress; + +import org.apache.qpid.server.security.access.firewall.HostnameFirewallRule; + +import junit.framework.TestCase; + +public class HostnameFirewallRuleTest extends TestCase +{ + private InetAddress _addressNotInRule; + + private HostnameFirewallRule _HostnameFirewallRule; + + @Override + protected void setUp() throws Exception + { + _addressNotInRule = InetAddress.getByName("127.0.0.1"); + } + + public void testSingleHostname() throws Exception + { + String hostnameInRule = "hostnameInRule"; + InetAddress addressWithMatchingHostname = mock(InetAddress.class); + when(addressWithMatchingHostname.getCanonicalHostName()).thenReturn(hostnameInRule); + + _HostnameFirewallRule = new HostnameFirewallRule(hostnameInRule); + + assertFalse(_HostnameFirewallRule.matches(_addressNotInRule)); + assertTrue(_HostnameFirewallRule.matches(addressWithMatchingHostname)); + } + + public void testSingleHostnameWilcard() throws Exception + { + String hostnameInRule = ".*FOO.*"; + InetAddress addressWithMatchingHostname = mock(InetAddress.class); + when(addressWithMatchingHostname.getCanonicalHostName()).thenReturn("xxFOOxx"); + + _HostnameFirewallRule = new HostnameFirewallRule(hostnameInRule); + + assertFalse(_HostnameFirewallRule.matches(_addressNotInRule)); + assertTrue(_HostnameFirewallRule.matches(addressWithMatchingHostname)); + } + + public void testMultipleHostnames() throws Exception + { + String[] hostnamesInRule = new String[] {"hostnameInRule1", "hostnameInRule2"}; + + _HostnameFirewallRule = new HostnameFirewallRule(hostnamesInRule); + + assertFalse(_HostnameFirewallRule.matches(_addressNotInRule)); + for (String hostnameInRule : hostnamesInRule) + { + InetAddress addressWithMatchingHostname = mock(InetAddress.class); + when(addressWithMatchingHostname.getCanonicalHostName()).thenReturn(hostnameInRule); + + assertTrue(_HostnameFirewallRule.matches(addressWithMatchingHostname)); + } + } + + public void testEqualsAndHashCode() + { + String hostname1 = "hostname1"; + String hostname2 = "hostname2"; + + HostnameFirewallRule rule = new HostnameFirewallRule(hostname1, hostname2); + HostnameFirewallRule equalRule = new HostnameFirewallRule(hostname1, hostname2); + + assertTrue(rule.equals(rule)); + assertTrue(rule.equals(equalRule)); + assertTrue(equalRule.equals(rule)); + + assertTrue(rule.hashCode() == equalRule.hashCode()); + + assertFalse("Different hostnames should cause rules to be unequal", + rule.equals(new HostnameFirewallRule(hostname1, "different-hostname"))); + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java new file mode 100644 index 0000000000..e521039db2 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.firewall; + +import java.net.InetAddress; + +import org.apache.qpid.server.security.access.firewall.NetworkFirewallRule; + +import junit.framework.TestCase; + +public class NetworkFirewallRuleTest extends TestCase +{ + private static final String LOCALHOST_IP = "127.0.0.1"; + private static final String OTHER_IP_1 = "192.168.23.1"; + private static final String OTHER_IP_2 = "192.168.23.2"; + + private InetAddress _addressNotInRule; + + private NetworkFirewallRule _networkFirewallRule; + + @Override + protected void setUp() throws Exception + { + _addressNotInRule = InetAddress.getByName(LOCALHOST_IP); + } + + public void testIpRule() throws Exception + { + String ipAddressInRule = OTHER_IP_1; + + _networkFirewallRule = new NetworkFirewallRule(ipAddressInRule); + + assertFalse(_networkFirewallRule.matches(_addressNotInRule)); + assertTrue(_networkFirewallRule.matches(InetAddress.getByName(ipAddressInRule))); + } + + public void testNetMask() throws Exception + { + String ipAddressInRule = "192.168.23.0/24"; + _networkFirewallRule = new NetworkFirewallRule(ipAddressInRule); + + assertFalse(_networkFirewallRule.matches(InetAddress.getByName("192.168.24.1"))); + assertTrue(_networkFirewallRule.matches(InetAddress.getByName("192.168.23.0"))); + assertTrue(_networkFirewallRule.matches(InetAddress.getByName("192.168.23.255"))); + } + + public void testWildcard() throws Exception + { + // Test xxx.xxx.* + + assertFalse(new NetworkFirewallRule("192.168.*") + .matches(InetAddress.getByName("192.169.1.0"))); + + assertTrue(new NetworkFirewallRule("192.168.*") + .matches(InetAddress.getByName("192.168.1.0"))); + + assertTrue(new NetworkFirewallRule("192.168.*") + .matches(InetAddress.getByName("192.168.255.255"))); + + // Test xxx.xxx.xxx.* + + assertFalse(new NetworkFirewallRule("192.168.1.*") + .matches(InetAddress.getByName("192.169.2.0"))); + + assertTrue(new NetworkFirewallRule("192.168.1.*") + .matches(InetAddress.getByName("192.168.1.0"))); + + assertTrue(new NetworkFirewallRule("192.168.1.*") + .matches(InetAddress.getByName("192.168.1.255"))); + } + + public void testMultipleNetworks() throws Exception + { + String[] ipAddressesInRule = new String[] {OTHER_IP_1, OTHER_IP_2}; + + _networkFirewallRule = new NetworkFirewallRule(ipAddressesInRule); + + assertFalse(_networkFirewallRule.matches(_addressNotInRule)); + for (String ipAddressInRule : ipAddressesInRule) + { + assertTrue(_networkFirewallRule.matches(InetAddress.getByName(ipAddressInRule))); + } + } + + public void testEqualsAndHashCode() + { + NetworkFirewallRule rule = new NetworkFirewallRule(LOCALHOST_IP, OTHER_IP_1); + NetworkFirewallRule equalRule = new NetworkFirewallRule(LOCALHOST_IP, OTHER_IP_1); + + assertTrue(rule.equals(rule)); + assertTrue(rule.equals(equalRule)); + assertTrue(equalRule.equals(rule)); + + assertTrue(rule.hashCode() == equalRule.hashCode()); + + assertFalse("Different networks should cause rules to be unequal", + rule.equals(new NetworkFirewallRule(LOCALHOST_IP, OTHER_IP_2))); + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java deleted file mode 100644 index 5db02d10ce..0000000000 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java +++ /dev/null @@ -1,355 +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.access.plugins; - -import java.util.Arrays; - -import junit.framework.TestCase; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.logging.UnitTestMessageLogger; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.TestLogActor; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; -import org.apache.qpid.server.security.access.Permission; -import org.apache.qpid.server.security.access.config.Rule; -import org.apache.qpid.server.security.access.config.RuleSet; -import org.apache.qpid.server.security.auth.sasl.TestPrincipalUtils; - -/** - * Unit test for ACL V2 plugin. - * - * This unit test tests the AccessControl class and it collaboration with {@link RuleSet}, - * {@link SecurityManager} and {@link CurrentActor}. The ruleset is configured programmatically, - * rather than from an external file. - * - * @see RuleSetTest - */ -public class AccessControlTest extends TestCase -{ - private AccessControl _plugin = null; // Class under test - private final UnitTestMessageLogger messageLogger = new UnitTestMessageLogger(); - - private void setUpGroupAccessControl() throws ConfigurationException - { - configureAccessControl(createGroupRuleSet()); - } - - private void configureAccessControl(final RuleSet rs) throws ConfigurationException - { - _plugin = (AccessControl) AccessControl.FACTORY.newInstance(createConfiguration(rs)); - SecurityManager.setThreadSubject(null); - CurrentActor.set(new TestLogActor(messageLogger)); - } - - private RuleSet createGroupRuleSet() - { - final RuleSet rs = new RuleSet(); - rs.addGroup("aclGroup1", Arrays.asList(new String[] {"member1", "Member2"})); - - // Rule expressed with username - rs.grant(0, "user1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - // Rule expressed with a acl group - rs.grant(1, "aclGroup1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - // Rule expressed with an external group - rs.grant(2, "extGroup1", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - // Catch all rule - rs.grant(3, Rule.ALL, Permission.DENY_LOG, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - - return rs; - } - - protected void tearDown() throws Exception - { - super.tearDown(); - SecurityManager.setThreadSubject(null); - } - - /** - * ACL plugin must always abstain if there is no subject attached to the thread. - */ - public void testNoSubjectAlwaysAbstains() throws ConfigurationException - { - setUpGroupAccessControl(); - SecurityManager.setThreadSubject(null); - - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.ABSTAIN, result); - } - - /** - * Tests that an allow rule expressed with a username allows an operation performed by a thread running - * with the same username. - */ - public void testUsernameAllowsOperation() throws ConfigurationException - { - setUpGroupAccessControl(); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user1")); - - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.ALLOWED, result); - } - - /** - * Tests that an allow rule expressed with an ACL groupname allows an operation performed by a thread running - * by a user who belongs to the same group.. - */ - public void testAclGroupMembershipAllowsOperation() throws ConfigurationException - { - setUpGroupAccessControl(); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("member1")); - - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.ALLOWED, result); - - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("Member2")); - - result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.ALLOWED, result); - } - - /** - * Tests that a deny rule expressed with an External groupname denies an operation performed by a thread running - * by a user who belongs to the same group. - */ - public void testExternalGroupMembershipDeniesOperation() throws ConfigurationException - { - setUpGroupAccessControl(); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user3", "extGroup1")); - - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.DENIED, result); - } - - /** - * Tests that the catch all deny denies the operation and logs with the logging actor. - */ - public void testCatchAllRuleDeniesUnrecognisedUsername() throws ConfigurationException - { - setUpGroupAccessControl(); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("unknown", "unkgroup1", "unkgroup2")); - - assertEquals("Expecting zero messages before test", 0, messageLogger.getLogMessages().size()); - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.DENIED, result); - - assertEquals("Expecting one message before test", 1, messageLogger.getLogMessages().size()); - assertTrue("Logged message does not contain expected string", messageLogger.messageContains(0, "ACL-1002")); - } - - /** - * Tests that a grant access method rule allows any access operation to be performed on any component - */ - public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnAllComponents() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user4 access right on any method in any component - rs.grant(1, "user4", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, new ObjectProperties(ObjectProperties.STAR)); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user4")); - - ObjectProperties actionProperties = new ObjectProperties("getName"); - actionProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); - assertEquals(Result.ALLOWED, result); - } - - /** - * Tests that a grant access method rule allows any access operation to be performed on a specified component - */ - public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user5 access right on any methods in "Test" component - ObjectProperties ruleProperties = new ObjectProperties(ObjectProperties.STAR); - ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - rs.grant(1, "user5", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user5")); - - ObjectProperties actionProperties = new ObjectProperties("getName"); - actionProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); - assertEquals(Result.ALLOWED, result); - - actionProperties.put(ObjectProperties.Property.COMPONENT, "Test2"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); - assertEquals(Result.DEFER, result); - } - - /** - * Tests that a grant access method rule allows any access operation to be performed on a specified component - */ - public void testAuthoriseAccessMethodWhenSpecifiedAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user6 access right on "getAttribute" method in "Test" component - ObjectProperties ruleProperties = new ObjectProperties("getAttribute"); - ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - rs.grant(1, "user6", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user6")); - - ObjectProperties properties = new ObjectProperties("getAttribute"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties.put(ObjectProperties.Property.COMPONENT, "Test2"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.DEFER, result); - - properties = new ObjectProperties("getAttribute2"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.DEFER, result); - } - - /** - * Tests that granting of all method rights on a method allows a specified operation to be performed on any component - */ - public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnSpecifiedMethodForAllComponents() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user8 all rights on method queryNames in all component - rs.grant(1, "user8", Permission.ALLOW, Operation.ALL, ObjectType.METHOD, new ObjectProperties("queryNames")); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user8")); - - ObjectProperties properties = new ObjectProperties(); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - properties.put(ObjectProperties.Property.NAME, "queryNames"); - - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties = new ObjectProperties("getAttribute"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); - assertEquals(Result.DEFER, result); - - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.DEFER, result); - } - - /** - * Tests that granting of all method rights allows any operation to be performed on any component - */ - public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnAllMethodsInAllComponents() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user9 all rights on any method in all component - rs.grant(1, "user9", Permission.ALLOW, Operation.ALL, ObjectType.METHOD, new ObjectProperties()); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user9")); - - ObjectProperties properties = new ObjectProperties("queryNames"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties = new ObjectProperties("getAttribute"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - } - - /** - * Tests that granting of access method rights with mask allows matching operations to be performed on the specified component - */ - public void testAuthoriseAccessMethodWhenMatchingAcessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user9 all rights on "getAttribute*" methods in Test component - ObjectProperties ruleProperties = new ObjectProperties(); - ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - ruleProperties.put(ObjectProperties.Property.NAME, "getAttribute*"); - - rs.grant(1, "user9", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user9")); - - ObjectProperties properties = new ObjectProperties("getAttributes"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties = new ObjectProperties("getAttribute"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties = new ObjectProperties("getAttribut"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.DEFER, result); - } - - /** - * Creates a configuration plugin for the {@link AccessControl} plugin. - */ - private ConfigurationPlugin createConfiguration(final RuleSet rs) - { - final ConfigurationPlugin cp = new ConfigurationPlugin() - { - @SuppressWarnings("unchecked") - public AccessControlConfiguration getConfiguration(final String plugin) - { - return new AccessControlConfiguration() - { - public RuleSet getRuleSet() - { - return rs; - } - }; - } - - public String[] getElementsProcessed() - { - throw new UnsupportedOperationException(); - } - }; - - return cp; - } -} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java new file mode 100644 index 0000000000..ca1f19098f --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java @@ -0,0 +1,69 @@ +package org.apache.qpid.server.security.access.plugins; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.security.AccessControl; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; + +public class DefaultAccessControlFactoryTest extends QpidTestCase +{ + public void testCreateInstanceWhenAclFileIsNotPresent() + { + DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); + Map attributes = new HashMap(); + AccessControl acl = factory.createInstance(attributes); + assertNull("ACL was created without a configuration file", acl); + } + + public void testCreateInstanceWhenAclFileIsSpecified() + { + File aclFile = TestFileUtils.createTempFile(this, ".acl", "ACL ALLOW all all"); + DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); + Map attributes = new HashMap(); + attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile.getAbsolutePath()); + AccessControl acl = factory.createInstance(attributes); + + assertNotNull("ACL was not created from acl file: " + aclFile.getAbsolutePath(), acl); + } + + public void testCreateInstanceWhenAclFileIsSpecifiedButDoesNotExist() + { + File aclFile = new File(TMP_FOLDER, "my-non-existing-acl-" + System.currentTimeMillis()); + assertFalse("ACL file " + aclFile.getAbsolutePath() + " actually exists but should not", aclFile.exists()); + DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); + Map attributes = new HashMap(); + attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile.getAbsolutePath()); + try + { + factory.createInstance(attributes); + fail("It should not be possible to create ACL from non existing file"); + } + catch (IllegalConfigurationException e) + { + assertTrue("Unexpected exception message", Pattern.matches("ACL file '.*' is not found", e.getMessage())); + } + } + + public void testCreateInstanceWhenAclFileIsSpecifiedAsNonString() + { + DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); + Map attributes = new HashMap(); + Integer aclFile = new Integer(0); + attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile); + try + { + factory.createInstance(attributes); + fail("It should not be possible to create ACL from Integer"); + } + catch (IllegalConfigurationException e) + { + assertEquals("Unexpected exception message", "Expected '" + DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE + + "' attribute value of type String but was " + Integer.class + ": " + aclFile, e.getMessage()); + } + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java new file mode 100644 index 0000000000..a8406308c0 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java @@ -0,0 +1,368 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.plugins; + +import static org.mockito.Mockito.*; + +import java.net.InetAddress; +import java.net.InetSocketAddress; + +import javax.security.auth.Subject; + +import junit.framework.TestCase; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.logging.UnitTestMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.TestLogActor; +import org.apache.qpid.server.security.Result; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.access.Permission; +import org.apache.qpid.server.security.access.config.Rule; +import org.apache.qpid.server.security.access.config.RuleSet; +import org.apache.qpid.server.security.auth.TestPrincipalUtils; + +/** + * In these tests, the ruleset is configured programmatically rather than from an external file. + * + * @see RuleSetTest + */ +public class DefaultAccessControlTest extends TestCase +{ + private static final String ALLOWED_GROUP = "allowed_group"; + private static final String DENIED_GROUP = "denied_group"; + + private DefaultAccessControl _plugin = null; // Class under test + private final UnitTestMessageLogger messageLogger = new UnitTestMessageLogger(); + + private void setUpGroupAccessControl() throws ConfigurationException + { + configureAccessControl(createGroupRuleSet()); + } + + private void configureAccessControl(final RuleSet rs) throws ConfigurationException + { + _plugin = new DefaultAccessControl(rs); + SecurityManager.setThreadSubject(null); + CurrentActor.set(new TestLogActor(messageLogger)); + } + + private RuleSet createGroupRuleSet() + { + final RuleSet rs = new RuleSet(); + + // Rule expressed with username + rs.grant(0, "user1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + // Rules expressed with groups + rs.grant(1, ALLOWED_GROUP, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + rs.grant(2, DENIED_GROUP, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + // Catch all rule + rs.grant(3, Rule.ALL, Permission.DENY_LOG, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + + return rs; + } + + protected void tearDown() throws Exception + { + super.tearDown(); + SecurityManager.setThreadSubject(null); + } + + /** + * ACL plugin must always abstain if there is no subject attached to the thread. + */ + public void testNoSubjectAlwaysAbstains() throws ConfigurationException + { + setUpGroupAccessControl(); + SecurityManager.setThreadSubject(null); + + final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + assertEquals(Result.ABSTAIN, result); + } + + /** + * Tests that an allow rule expressed with a username allows an operation performed by a thread running + * with the same username. + */ + public void testUsernameAllowsOperation() throws ConfigurationException + { + setUpGroupAccessControl(); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user1")); + + final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + assertEquals(Result.ALLOWED, result); + } + + /** + * Tests that an allow rule expressed with an ACL groupname allows an operation performed by a thread running + * by a user who belongs to the same group.. + */ + public void testGroupMembershipAllowsOperation() throws ConfigurationException + { + setUpGroupAccessControl(); + + authoriseAndAssertResult(Result.ALLOWED, "member of allowed group", ALLOWED_GROUP); + authoriseAndAssertResult(Result.DENIED, "member of denied group", DENIED_GROUP); + authoriseAndAssertResult(Result.ALLOWED, "another member of allowed group", ALLOWED_GROUP); + } + + /** + * Tests that a deny rule expressed with a groupname denies an operation performed by a thread running + * by a user who belongs to the same group. + */ + public void testGroupMembershipDeniesOperation() throws ConfigurationException + { + setUpGroupAccessControl(); + authoriseAndAssertResult(Result.DENIED, "user3", DENIED_GROUP); + } + + /** + * Tests that the catch all deny denies the operation and logs with the logging actor. + */ + public void testCatchAllRuleDeniesUnrecognisedUsername() throws ConfigurationException + { + setUpGroupAccessControl(); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("unknown", "unkgroup1", "unkgroup2")); + + assertEquals("Expecting zero messages before test", 0, messageLogger.getLogMessages().size()); + final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + assertEquals(Result.DENIED, result); + + assertEquals("Expecting one message before test", 1, messageLogger.getLogMessages().size()); + assertTrue("Logged message does not contain expected string", messageLogger.messageContains(0, "ACL-1002")); + } + + /** + * Tests that a grant access method rule allows any access operation to be performed on any component + */ + public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnAllComponents() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user4 access right on any method in any component + rs.grant(1, "user4", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, new ObjectProperties(ObjectProperties.STAR)); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user4")); + + ObjectProperties actionProperties = new ObjectProperties("getName"); + actionProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + + final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); + assertEquals(Result.ALLOWED, result); + } + + /** + * Tests that a grant access method rule allows any access operation to be performed on a specified component + */ + public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user5 access right on any methods in "Test" component + ObjectProperties ruleProperties = new ObjectProperties(ObjectProperties.STAR); + ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + rs.grant(1, "user5", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user5")); + + ObjectProperties actionProperties = new ObjectProperties("getName"); + actionProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); + assertEquals(Result.ALLOWED, result); + + actionProperties.put(ObjectProperties.Property.COMPONENT, "Test2"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); + assertEquals(Result.DEFER, result); + } + + public void testAccess() throws Exception + { + Subject subject = TestPrincipalUtils.createTestSubject("user1"); + SecurityManager.setThreadSubject(subject); + + RuleSet mockRuleSet = mock(RuleSet.class); + + InetAddress inetAddress = InetAddress.getLocalHost(); + InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 1); + + DefaultAccessControl accessControl = new DefaultAccessControl(mockRuleSet); + + accessControl.access(ObjectType.VIRTUALHOST, inetSocketAddress); + + verify(mockRuleSet).check(subject, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY, inetAddress); + } + + public void testAccessIsDeniedIfRuleThrowsException() throws Exception + { + Subject subject = TestPrincipalUtils.createTestSubject("user1"); + SecurityManager.setThreadSubject(subject); + + InetAddress inetAddress = InetAddress.getLocalHost(); + InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 1); + + RuleSet mockRuleSet = mock(RuleSet.class); + when(mockRuleSet.check( + subject, + Operation.ACCESS, + ObjectType.VIRTUALHOST, + ObjectProperties.EMPTY, + inetAddress)).thenThrow(new RuntimeException()); + + DefaultAccessControl accessControl = new DefaultAccessControl(mockRuleSet); + Result result = accessControl.access(ObjectType.VIRTUALHOST, inetSocketAddress); + + assertEquals(Result.DENIED, result); + } + + + /** + * Tests that a grant access method rule allows any access operation to be performed on a specified component + */ + public void testAuthoriseAccessMethodWhenSpecifiedAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user6 access right on "getAttribute" method in "Test" component + ObjectProperties ruleProperties = new ObjectProperties("getAttribute"); + ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + rs.grant(1, "user6", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user6")); + + ObjectProperties properties = new ObjectProperties("getAttribute"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties.put(ObjectProperties.Property.COMPONENT, "Test2"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.DEFER, result); + + properties = new ObjectProperties("getAttribute2"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.DEFER, result); + } + + /** + * Tests that granting of all method rights on a method allows a specified operation to be performed on any component + */ + public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnSpecifiedMethodForAllComponents() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user8 all rights on method queryNames in all component + rs.grant(1, "user8", Permission.ALLOW, Operation.ALL, ObjectType.METHOD, new ObjectProperties("queryNames")); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user8")); + + ObjectProperties properties = new ObjectProperties(); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + properties.put(ObjectProperties.Property.NAME, "queryNames"); + + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties = new ObjectProperties("getAttribute"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); + assertEquals(Result.DEFER, result); + + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.DEFER, result); + } + + /** + * Tests that granting of all method rights allows any operation to be performed on any component + */ + public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnAllMethodsInAllComponents() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user9 all rights on any method in all component + rs.grant(1, "user9", Permission.ALLOW, Operation.ALL, ObjectType.METHOD, new ObjectProperties()); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user9")); + + ObjectProperties properties = new ObjectProperties("queryNames"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties = new ObjectProperties("getAttribute"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + } + + /** + * Tests that granting of access method rights with mask allows matching operations to be performed on the specified component + */ + public void testAuthoriseAccessMethodWhenMatchingAcessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user9 all rights on "getAttribute*" methods in Test component + ObjectProperties ruleProperties = new ObjectProperties(); + ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + ruleProperties.put(ObjectProperties.Property.NAME, "getAttribute*"); + + rs.grant(1, "user9", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user9")); + + ObjectProperties properties = new ObjectProperties("getAttributes"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties = new ObjectProperties("getAttribute"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties = new ObjectProperties("getAttribut"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.DEFER, result); + } + + private void authoriseAndAssertResult(Result expectedResult, String userName, String... groups) + { + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject(userName, groups)); + + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + assertEquals(expectedResult, result); + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java deleted file mode 100644 index c2282694fb..0000000000 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java +++ /dev/null @@ -1,394 +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.access.plugins; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.PrintWriter; -import java.util.Map; - -import junit.framework.TestCase; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectProperties.Property; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; -import org.apache.qpid.server.security.access.config.ConfigurationFile; -import org.apache.qpid.server.security.access.config.PlainConfiguration; -import org.apache.qpid.server.security.access.config.Rule; -import org.apache.qpid.server.security.access.config.RuleSet; - -/** - * These tests check that the ACL file parsing works correctly. - * - * For each message that can be returned in a {@link ConfigurationException}, an ACL file is created that should trigger this - * particular message. - */ -public class PlainConfigurationTest extends TestCase -{ - private PlainConfiguration writeACLConfig(String...aclData) throws Exception - { - File acl = File.createTempFile(getClass().getName() + getName(), "acl"); - acl.deleteOnExit(); - - // Write ACL file - PrintWriter aclWriter = new PrintWriter(new FileWriter(acl)); - for (String line : aclData) - { - aclWriter.println(line); - } - aclWriter.close(); - - // Load ruleset - PlainConfiguration configFile = new PlainConfiguration(acl); - configFile.load(); - return configFile; - } - - public void testMissingACLConfig() throws Exception - { - try - { - // Load ruleset - ConfigurationFile configFile = new PlainConfiguration(new File("doesnotexist")); - configFile.load(); - - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.CONFIG_NOT_FOUND_MSG, "doesnotexist"), ce.getMessage()); - assertTrue(ce.getCause() instanceof FileNotFoundException); - } - } - - public void testACLFileSyntaxContinuation() throws Exception - { - try - { - writeACLConfig("ACL ALLOW ALL \\ ALL"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PREMATURE_CONTINUATION_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxTokens() throws Exception - { - try - { - writeACLConfig("ACL unparsed ALL ALL"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PARSE_TOKEN_FAILED_MSG, 1), ce.getMessage()); - assertTrue(ce.getCause() instanceof IllegalArgumentException); - assertEquals("Not a valid permission: unparsed", ce.getCause().getMessage()); - } - } - - public void testACLFileSyntaxNotEnoughGroup() throws Exception - { - try - { - writeACLConfig("GROUP blah"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_GROUP_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxNotEnoughACL() throws Exception - { - try - { - writeACLConfig("ACL ALLOW"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_ACL_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxNotEnoughConfig() throws Exception - { - try - { - writeACLConfig("CONFIG"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxNotEnough() throws Exception - { - try - { - writeACLConfig("INVALID"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxPropertyKeyOnly() throws Exception - { - try - { - writeACLConfig("ACL ALLOW adk CREATE QUEUE name"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PROPERTY_KEY_ONLY_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxPropertyNoEquals() throws Exception - { - try - { - writeACLConfig("ACL ALLOW adk CREATE QUEUE name test"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PROPERTY_NO_EQUALS_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxPropertyNoValue() throws Exception - { - try - { - writeACLConfig("ACL ALLOW adk CREATE QUEUE name ="); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PROPERTY_NO_VALUE_MSG, 1), ce.getMessage()); - } - } - - /** - * Tests interpretation of an acl rule with no object properties. - * - */ - public void testValidRule() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL DENY-LOG user1 ACCESS VIRTUALHOST"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); - assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule with object properties quoted in single quotes. - */ - public void testValidRuleWithSingleQuotedProperty() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE name = \'value\'"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "all", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.CREATE, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); - final ObjectProperties expectedProperties = new ObjectProperties(); - expectedProperties.setName("value"); - assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule with object properties quoted in double quotes. - */ - public void testValidRuleWithDoubleQuotedProperty() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE name = \"value\""); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "all", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.CREATE, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); - final ObjectProperties expectedProperties = new ObjectProperties(); - expectedProperties.setName("value"); - assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule with many object properties. - */ - public void testValidRuleWithManyProperties() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL ALLOW admin DELETE QUEUE name=name1 owner = owner1"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "admin", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.DELETE, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.QUEUE, rule.getAction().getObjectType()); - final ObjectProperties expectedProperties = new ObjectProperties(); - expectedProperties.setName("name1"); - expectedProperties.put(Property.OWNER, "owner1"); - assertEquals("Rule has unexpected operation", expectedProperties, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule with object properties containing wildcards. Values containing - * hashes must be quoted otherwise they are interpreted as comments. - */ - public void testValidRuleWithWildcardProperties() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE routingKey = \'news.#\'", - "ACL ALLOW all CREATE EXCHANGE routingKey = \'news.co.#\'", - "ACL ALLOW all CREATE EXCHANGE routingKey = *.co.medellin"); - final RuleSet rs = config.getConfiguration(); - assertEquals(3, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(3, rules.size()); - final Rule rule1 = rules.get(0); - assertEquals("Rule has unexpected identity", "all", rule1.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.CREATE, rule1.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule1.getAction().getObjectType()); - final ObjectProperties expectedProperties1 = new ObjectProperties(); - expectedProperties1.put(Property.ROUTING_KEY,"news.#"); - assertEquals("Rule has unexpected object properties", expectedProperties1, rule1.getAction().getProperties()); - - final Rule rule2 = rules.get(10); - final ObjectProperties expectedProperties2 = new ObjectProperties(); - expectedProperties2.put(Property.ROUTING_KEY,"news.co.#"); - assertEquals("Rule has unexpected object properties", expectedProperties2, rule2.getAction().getProperties()); - - final Rule rule3 = rules.get(20); - final ObjectProperties expectedProperties3 = new ObjectProperties(); - expectedProperties3.put(Property.ROUTING_KEY,"*.co.medellin"); - assertEquals("Rule has unexpected object properties", expectedProperties3, rule3.getAction().getProperties()); - } - - /** - * Tests that rules are case insignificant. - */ - public void testMixedCaseRuleInterpretation() throws Exception - { - final PlainConfiguration config = writeACLConfig("AcL deny-LOG User1 BiND Exchange Name=AmQ.dIrect"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "User1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.BIND, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); - final ObjectProperties expectedProperties = new ObjectProperties("AmQ.dIrect"); - assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); - } - - /** - * Tests whitespace is supported. Note that currently the Java implementation permits comments to - * be introduced anywhere in the ACL, whereas the C++ supports only whitespace at the beginning of - * of line. - */ - public void testCommentsSuppported() throws Exception - { - final PlainConfiguration config = writeACLConfig("#Comment", - "ACL DENY-LOG user1 ACCESS VIRTUALHOST # another comment", - " # final comment with leading whitespace"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); - assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule using mixtures of tabs/spaces as token separators. - * - */ - public void testWhitespace() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL\tDENY-LOG\t\t user1\t \tACCESS VIRTUALHOST"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); - assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl utilising line continuation. - */ - public void testLineContination() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL DENY-LOG user1 \\", - "ACCESS VIRTUALHOST"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); - assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); - } - -} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java index f7cc60543d..181d693614 100644 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.security.access.plugins; import java.security.Principal; -import java.util.Arrays; import javax.security.auth.Subject; @@ -34,8 +33,7 @@ import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.access.Permission; import org.apache.qpid.server.security.access.config.Rule; import org.apache.qpid.server.security.access.config.RuleSet; -import org.apache.qpid.server.security.auth.sasl.TestPrincipalUtils; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.TestPrincipalUtils; import org.apache.qpid.test.utils.QpidTestCase; /** @@ -46,10 +44,7 @@ import org.apache.qpid.test.utils.QpidTestCase; * access control mechanism is validated by checking whether operations would be authorised by calling the * {@link RuleSet#check(Principal, Operation, ObjectType, ObjectProperties)} method. * - * It ensure that permissions can be granted correctly on users directly, ACL groups (that is those - * groups declared directly in the ACL itself), and External groups (that is a group from an External - * Authentication Provider, such as an LDAP). - + * It ensure that permissions can be granted correctly on users directly and on groups. */ public class RuleSetTest extends QpidTestCase { @@ -316,63 +311,36 @@ public class RuleSetTest extends QpidTestCase assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); } - /** - * Tests support for ACL groups (i.e. inline groups declared in the ACL file itself). - */ - public void testAclGroupsSupported() + public void testGroupsSupported() { - assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera", "userb"}))); - - _ruleSet.grant(1, "aclgroup", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(1, _ruleSet.getRuleCount()); - - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - assertEquals(Result.DEFER, _ruleSet.check(TestPrincipalUtils.createTestSubject("userc"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - } - - /** - * Tests support for nested ACL groups. - */ - public void testNestedAclGroupsSupported() - { - assertTrue(_ruleSet.addGroup("aclgroup1", Arrays.asList(new String[] {"userb"}))); - assertTrue(_ruleSet.addGroup("aclgroup2", Arrays.asList(new String[] {"usera", "aclgroup1"}))); - - _ruleSet.grant(1, "aclgroup2", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(1, _ruleSet.getRuleCount()); + String allowGroup = "allowGroup"; + String deniedGroup = "deniedGroup"; - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - } + _ruleSet.grant(1, allowGroup, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(2, deniedGroup, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - /** - * Tests support for nested External groups (i.e. those groups coming from an external source such as an LDAP). - */ - public void testExternalGroupsSupported() - { - _ruleSet.grant(1, "extgroup1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - _ruleSet.grant(2, "extgroup2", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); assertEquals(2, _ruleSet.getRuleCount()); - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera", "extgroup1"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); - assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb", "extgroup2"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera", allowGroup),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb", deniedGroup),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.DEFER, _ruleSet.check(TestPrincipalUtils.createTestSubject("user", "group not mentioned in acl"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); } /** * Rule order in the ACL determines the outcome of the check. This test ensures that a user who is - * granted explicit permission on an object, is granted that access even although late a group + * granted explicit permission on an object, is granted that access even though a group * to which the user belongs is later denied the permission. */ public void testAllowDeterminedByRuleOrder() { - assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"}))); + String group = "group"; + String user = "user"; - _ruleSet.grant(1, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - _ruleSet.grant(2, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(1, user, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(2, group, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); assertEquals(2, _ruleSet.getRuleCount()); - assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject(user, group),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); } /** @@ -381,13 +349,33 @@ public class RuleSetTest extends QpidTestCase */ public void testDenyDeterminedByRuleOrder() { - assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"}))); + String group = "aclgroup"; + String user = "usera"; - _ruleSet.grant(1, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - _ruleSet.grant(2, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(1, group, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(2, user, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); assertEquals(2, _ruleSet.getRuleCount()); - assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject(user, group),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + } + + public void testUserInMultipleGroups() + { + String allowedGroup = "group1"; + String deniedGroup = "group2"; + + _ruleSet.grant(1, allowedGroup, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + _ruleSet.grant(2, deniedGroup, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + + Subject subjectInBothGroups = TestPrincipalUtils.createTestSubject("user", allowedGroup, deniedGroup); + Subject subjectInDeniedGroupAndOneOther = TestPrincipalUtils.createTestSubject("user", deniedGroup, "some other group"); + Subject subjectInAllowedGroupAndOneOther = TestPrincipalUtils.createTestSubject("user", allowedGroup, "some other group"); + + assertEquals(Result.ALLOWED, _ruleSet.check(subjectInBothGroups,Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + + assertEquals(Result.DENIED, _ruleSet.check(subjectInDeniedGroupAndOneOther,Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); + + assertEquals(Result.ALLOWED, _ruleSet.check(subjectInAllowedGroupAndOneOther,Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY)); } } diff --git a/java/broker-plugins/firewall/MANIFEST.MF b/java/broker-plugins/firewall/MANIFEST.MF deleted file mode 100644 index a302921d03..0000000000 --- a/java/broker-plugins/firewall/MANIFEST.MF +++ /dev/null @@ -1,34 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Qpid Broker-Plugins Firewall -Bundle-SymbolicName: broker-plugins-firewall -Bundle-Description: Firewall plugin for Qpid. -Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt -Bundle-DocURL: http://www.apache.org/ -Bundle-Version: 1.0.0 -Bundle-Activator: org.apache.qpid.server.security.access.plugins.FirewallActivator -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ClassPath: . -Bundle-ActivationPolicy: lazy -Import-Package: org.apache.qpid, - org.apache.qpid.framing, - org.apache.qpid.protocol, - org.apache.qpid.server.configuration, - org.apache.qpid.server.configuration.plugins, - org.apache.qpid.server.exchange, - org.apache.qpid.server.plugins, - org.apache.qpid.server.queue, - org.apache.qpid.server.security, - org.apache.qpid.server.security.access, - org.apache.qpid.server.virtualhost, - org.apache.qpid.util, - org.apache.commons.configuration;version=1.0.0, - org.apache.commons.lang;version=1.0.0, - org.apache.commons.lang.builder;version=1.0.0, - org.apache.log4j;version=1.0.0, - javax.management;version=1.0.0, - javax.management.openmbean;version=1.0.0, - org.osgi.util.tracker;version=1.0.0, - org.osgi.framework;version=1.3 -Private-Package: org.apache.qpid.server.security.access.config -Export-Package: org.apache.qpid.server.security.access.plugins;uses:="org.osgi.framework" diff --git a/java/broker-plugins/firewall/build.xml b/java/broker-plugins/firewall/build.xml deleted file mode 100644 index 6ae6a35b89..0000000000 --- a/java/broker-plugins/firewall/build.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/config/FirewallException.java b/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/config/FirewallException.java deleted file mode 100644 index a9e3fdc242..0000000000 --- a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/config/FirewallException.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.security.access.config; - -/** - * Firewall plugin exception. - */ -public class FirewallException extends Exception -{ - /** serialVersionUID */ - private static final long serialVersionUID = 4526157149690917805L; - - public FirewallException() { - super(); - } - - public FirewallException(String message) { - super(message); - } - - public FirewallException(String message, Throwable cause) { - super(message, cause); - } - - public FirewallException(Throwable cause) { - super(cause); - } -} \ No newline at end of file diff --git a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/config/FirewallRule.java b/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/config/FirewallRule.java deleted file mode 100644 index ecec4b0cec..0000000000 --- a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/config/FirewallRule.java +++ /dev/null @@ -1,136 +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.access.config; - -import org.apache.qpid.server.security.Result; -import org.apache.qpid.util.NetMatcher; - -import java.net.InetAddress; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; - -public class FirewallRule -{ - public static final String ALLOW = "ALLOW"; - public static final String DENY = "DENY"; - - private static final long DNS_TIMEOUT = 30000; - private static final ExecutorService DNS_LOOKUP = Executors.newCachedThreadPool(); - - private Result _access; - private NetMatcher _network; - private Pattern[] _hostnamePatterns; - - public FirewallRule(String access, List networks, List hostnames) - { - _access = (access.equalsIgnoreCase(ALLOW)) ? Result.ALLOWED : Result.DENIED; - - if (networks != null && networks.size() > 0) - { - String[] networkStrings = objListToStringArray(networks); - _network = new NetMatcher(networkStrings); - } - - if (hostnames != null && hostnames.size() > 0) - { - int i = 0; - _hostnamePatterns = new Pattern[hostnames.size()]; - for (String hostname : objListToStringArray(hostnames)) - { - _hostnamePatterns[i++] = Pattern.compile(hostname); - } - } - } - - private String[] objListToStringArray(List objList) - { - String[] networkStrings = new String[objList.size()]; - int i = 0; - for (Object network : objList) - { - networkStrings[i++] = (String) network; - } - return networkStrings; - } - - public boolean match(InetAddress remote) throws FirewallException - { - if (_hostnamePatterns != null) - { - String hostname = getHostname(remote); - if (hostname == null) - { - throw new FirewallException("DNS lookup failed"); - } - for (Pattern pattern : _hostnamePatterns) - { - if (pattern.matcher(hostname).matches()) - { - return true; - } - } - return false; - } - else - { - return _network.matchInetNetwork(remote); - } - } - - /** - * @param remote the InetAddress to look up - * @return the hostname, null if not found, takes longer than 30s to find or otherwise fails - */ - private String getHostname(final InetAddress remote) throws FirewallException - { - FutureTask lookup = new FutureTask(new Callable() - { - public String call() - { - return remote.getCanonicalHostName(); - } - }); - DNS_LOOKUP.execute(lookup); - - try - { - return lookup.get(DNS_TIMEOUT, TimeUnit.MILLISECONDS); - } - catch (Exception e) - { - return null; - } - finally - { - lookup.cancel(true); - } - } - - public Result getAccess() - { - return _access; - } -} \ No newline at end of file diff --git a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/Firewall.java b/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/Firewall.java deleted file mode 100644 index 40a65fddba..0000000000 --- a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/Firewall.java +++ /dev/null @@ -1,137 +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.access.plugins; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.security.AbstractPlugin; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.SecurityPluginFactory; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; -import org.apache.qpid.server.security.access.config.FirewallException; -import org.apache.qpid.server.security.access.config.FirewallRule; - -import java.net.InetAddress; -import java.net.InetSocketAddress; - -public class Firewall extends AbstractPlugin -{ - public static final SecurityPluginFactory FACTORY = new SecurityPluginFactory() - { - public Firewall newInstance(ConfigurationPlugin config) throws ConfigurationException - { - FirewallConfiguration configuration = config.getConfiguration(FirewallConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - return null; - } - - Firewall plugin = new Firewall(); - plugin.configure(configuration); - return plugin; - } - - public Class getPluginClass() - { - return Firewall.class; - } - - public String getPluginName() - { - return Firewall.class.getName(); - } - }; - - private Result _default = Result.ABSTAIN; - private FirewallRule[] _rules; - - public Result getDefault() - { - return _default; - } - - public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) - { - return Result.ABSTAIN; // We only deal with access requests - } - - public Result access(ObjectType objectType, Object instance) - { - if (objectType != ObjectType.VIRTUALHOST) - { - return Result.ABSTAIN; // We are only interested in access to virtualhosts - } - - if (!(instance instanceof InetSocketAddress)) - { - return Result.ABSTAIN; // We need an internet address - } - - InetAddress address = ((InetSocketAddress) instance).getAddress(); - - try - { - for (FirewallRule rule : _rules) - { - boolean match = rule.match(address); - if (match) - { - return rule.getAccess(); - } - } - return getDefault(); - } - catch (FirewallException fe) - { - return Result.DENIED; - } - } - - - public void configure(ConfigurationPlugin config) - { - super.configure(config); - FirewallConfiguration firewallConfiguration = (FirewallConfiguration) getConfig(); - - // Get default action - _default = firewallConfiguration.getDefaultAction(); - - Configuration finalConfig = firewallConfiguration.getConfiguration(); - - // all rules must have an access attribute - int numRules = finalConfig.getList("rule[@access]").size(); - _rules = new FirewallRule[numRules]; - for (int i = 0; i < numRules; i++) - { - FirewallRule rule = new FirewallRule(finalConfig.getString("rule(" + i + ")[@access]"), - finalConfig.getList("rule(" + i + ")[@network]"), - finalConfig.getList("rule(" + i + ")[@hostname]")); - _rules[i] = rule; - } - - } -} diff --git a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/FirewallActivator.java b/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/FirewallActivator.java deleted file mode 100644 index 1669352085..0000000000 --- a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/FirewallActivator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.security.access.plugins; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.security.SecurityPluginActivator; -import org.apache.qpid.server.security.SecurityPluginFactory; - -/** - * The OSGi {@link org.osgi.framework.BundleActivator} for {@link Firewall}. - */ -public class FirewallActivator extends SecurityPluginActivator -{ - public SecurityPluginFactory getFactory() - { - return Firewall.FACTORY; - } - - public ConfigurationPluginFactory getConfigurationFactory() - { - return FirewallConfiguration.FACTORY; - } -} diff --git a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/FirewallConfiguration.java b/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/FirewallConfiguration.java deleted file mode 100644 index 010d1652f0..0000000000 --- a/java/broker-plugins/firewall/src/main/java/org/apache/qpid/server/security/access/plugins/FirewallConfiguration.java +++ /dev/null @@ -1,103 +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.access.plugins; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.access.config.FirewallRule; - -import java.util.Arrays; -import java.util.List; - -public class FirewallConfiguration extends ConfigurationPlugin -{ - private CompositeConfiguration _finalConfig; - - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - ConfigurationPlugin instance = new FirewallConfiguration(); - instance.setConfiguration(path, config); - return instance; - } - - public List getParentPaths() - { - return Arrays.asList("security.firewall", "virtualhosts.virtualhost.security.firewall"); - } - }; - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - - public Configuration getConfiguration() - { - return _finalConfig; - } - - public Result getDefaultAction() - { - String defaultAction = getConfig().getString("[@default-action]"); - if (defaultAction == null) - { - return Result.ABSTAIN; - } - else if (defaultAction.equalsIgnoreCase(FirewallRule.ALLOW)) - { - return Result.ALLOWED; - } - else - { - return Result.DENIED; - } - } - - - - @Override - public void validateConfiguration() throws ConfigurationException - { - // Valid Configuration either has xml links to new files - _finalConfig = new CompositeConfiguration(getConfig()); - List subFiles = getConfig().getList("xml[@fileName]"); - for (Object subFile : subFiles) - { - _finalConfig.addConfiguration(new XMLConfiguration((String) subFile)); - } - - // all rules must have an access attribute or a default value - if (_finalConfig.getList("rule[@access]").size() == 0 && - getConfig().getString("[@default-action]") == null) - { - throw new ConfigurationException("No rules or default-action found in firewall configuration."); - } - } - -} diff --git a/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java b/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java deleted file mode 100644 index 8969363979..0000000000 --- a/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallConfigurationTest.java +++ /dev/null @@ -1,322 +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.access; - -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.test.utils.QpidTestCase; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.net.InetSocketAddress; - -public class FirewallConfigurationTest extends QpidTestCase -{ - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - ApplicationRegistry.remove(); - } - - public void testFirewallConfiguration() throws Exception - { - // Write out config - File mainFile = File.createTempFile(getClass().getName(), null); - mainFile.deleteOnExit(); - writeConfigFile(mainFile, false); - - // Load config - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - - // Test config - assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535))); - assertTrue(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.1.2.3", 65535))); - } - - public void testCombinedConfigurationFirewall() throws Exception - { - // Write out config - File mainFile = File.createTempFile(getClass().getName(), null); - File fileA = File.createTempFile(getClass().getName(), null); - File fileB = File.createTempFile(getClass().getName(), null); - - mainFile.deleteOnExit(); - fileA.deleteOnExit(); - fileB.deleteOnExit(); - - FileWriter out = new FileWriter(mainFile); - out.write(""); - out.write(""); - out.write(""); - out.close(); - - out = new FileWriter(fileA); - out.write("\n"); - out.write("\t${QPID_HOME}/lib/plugins\n"); - out.write("\t${QPID_WORK}/cache\n"); - out.write("\tfalse\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\torg.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\t\tpasswordFile\n"); - out.write("\t\t\t\t\t\t/dev/null\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\ttest\n"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\n"); - out.close(); - - out = new FileWriter(fileB); - out.write("\n"); - out.write("\t"); - out.write("\n"); - out.close(); - - // Load config - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - - // Test config - assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535))); - } - - public void testConfigurationFirewallReload() throws Exception - { - // Write out config - File mainFile = File.createTempFile(getClass().getName(), null); - - mainFile.deleteOnExit(); - writeConfigFile(mainFile, false); - - // Load config - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - - // Test config - assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535))); - - // Switch to deny the connection - writeConfigFile(mainFile, true); - - reg.getConfiguration().reparseConfigFileSecuritySections(); - - assertTrue(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535))); - } - - public void testCombinedConfigurationFirewallReload() throws Exception - { - // Write out config - File mainFile = File.createTempFile(getClass().getName(), null); - File fileA = File.createTempFile(getClass().getName(), null); - File fileB = File.createTempFile(getClass().getName(), null); - - mainFile.deleteOnExit(); - fileA.deleteOnExit(); - fileB.deleteOnExit(); - - FileWriter out = new FileWriter(mainFile); - out.write(""); - out.write(""); - out.write(""); - out.close(); - - out = new FileWriter(fileA); - out.write("\n"); - out.write("\t${QPID_HOME}/lib/plugins\n"); - out.write("\tfalse\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\torg.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\t\tpasswordFile\n"); - out.write("\t\t\t\t\t\t/dev/null\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\ttest\n"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\n"); - out.close(); - - out = new FileWriter(fileB); - out.write("\n"); - out.write("\t"); - out.write("\n"); - out.close(); - - // Load config - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - - // Test config - assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535))); - - RandomAccessFile fileBRandom = new RandomAccessFile(fileB, "rw"); - fileBRandom.setLength(0); - fileBRandom.seek(0); - fileBRandom.close(); - - out = new FileWriter(fileB); - out.write("\n"); - out.write("\t"); - out.write("\n"); - out.close(); - - reg.getConfiguration().reparseConfigFileSecuritySections(); - - assertTrue(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535))); - - fileBRandom = new RandomAccessFile(fileB, "rw"); - fileBRandom.setLength(0); - fileBRandom.seek(0); - fileBRandom.close(); - - out = new FileWriter(fileB); - out.write("\n"); - out.write("\t"); - out.write("\n"); - out.close(); - - reg.getConfiguration().reparseConfigFileSecuritySections(); - - assertFalse(reg.getSecurityManager().accessVirtualhost("test", new InetSocketAddress("127.0.0.1", 65535))); - } - - private void writeFirewallVhostsFile(File vhostsFile, boolean allow) throws IOException - { - FileWriter out = new FileWriter(vhostsFile); - String ipAddr = "127.0.0.1"; // FIXME: get this from InetAddress.getLocalHost().getAddress() ? - out.write(""); - out.write("test"); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.close(); - } - - private void writeConfigFile(File mainFile, boolean allow) throws IOException { - writeConfigFile(mainFile, allow, true, null, "test"); - } - - /* - XMLConfiguration config = new XMLConfiguration(mainFile); - PluginManager pluginManager = new MockPluginManager(""); - SecurityManager manager = new SecurityManager(config, pluginManager, Firewall.FACTORY); - - */ - private void writeConfigFile(File mainFile, boolean allow, boolean includeVhosts, File vhostsFile, String name) throws IOException { - FileWriter out = new FileWriter(mainFile); - out.write("\n"); - out.write("\t${QPID_HOME}/lib/plugins\n"); - out.write("\tfalse\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\torg.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\t\tpasswordFile\n"); - out.write("\t\t\t\t\t\t/dev/null\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t"); - out.write("\t\t\n"); - out.write("\t\n"); - if (includeVhosts) - { - out.write("\t\n"); - out.write("\t\ttest\n"); - out.write("\t\t\n"); - out.write(String.format("\t\t\t%s\n", name)); - out.write("\t\t\n"); - out.write("\t\n"); - } - if (vhostsFile != null) - { - out.write("\t"+vhostsFile.getAbsolutePath()+"\n"); - } - out.write("\n"); - out.close(); - } - - /** - * Test that configuration loads correctly when virtual hosts are specified in an external - * configuration file only. - *

- * Test for QPID-2360 - */ - public void testExternalFirewallVirtualhostXMLFile() throws Exception - { - // Write out config - File mainFile = File.createTempFile(getClass().getName(), "config"); - mainFile.deleteOnExit(); - File vhostsFile = File.createTempFile(getClass().getName(), "vhosts"); - vhostsFile.deleteOnExit(); - writeConfigFile(mainFile, false, false, vhostsFile, null); - writeFirewallVhostsFile(vhostsFile, false); - - // Load config - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - - // Test config - VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry(); - VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); - - assertEquals("Incorrect virtualhost count", 1, virtualHostRegistry.getVirtualHosts().size()); - assertEquals("Incorrect virtualhost name", "test", virtualHost.getName()); - } -} diff --git a/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallPluginTest.java b/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallPluginTest.java deleted file mode 100644 index 2004852c48..0000000000 --- a/java/broker-plugins/firewall/src/test/java/org/apache/qpid/server/security/access/FirewallPluginTest.java +++ /dev/null @@ -1,294 +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.access; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.access.plugins.Firewall; -import org.apache.qpid.server.security.access.plugins.FirewallConfiguration; -import org.apache.qpid.server.util.TestApplicationRegistry; -import org.apache.qpid.test.utils.QpidTestCase; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -public class FirewallPluginTest extends QpidTestCase -{ - public class RuleInfo - { - private String _access; - private String _network; - private String _hostname; - - public void setAccess(String _access) - { - this._access = _access; - } - - public String getAccess() - { - return _access; - } - - public void setNetwork(String _network) - { - this._network = _network; - } - - public String getNetwork() - { - return _network; - } - - public void setHostname(String _hostname) - { - this._hostname = _hostname; - } - - public String getHostname() - { - return _hostname; - } - } - - // IP address - private SocketAddress _address; - private ServerConfiguration _serverConfig; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - _serverConfig = new ServerConfiguration(new XMLConfiguration()); - ApplicationRegistry.initialise(new TestApplicationRegistry(_serverConfig)); - _address = new InetSocketAddress("127.0.0.1", 65535); - } - - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - ApplicationRegistry.remove(); - } - private Firewall initialisePlugin(String defaultAction, RuleInfo[] rules) throws IOException, ConfigurationException - { - // Create sample config file - File confFile = File.createTempFile(getClass().getSimpleName()+"conffile", null); - confFile.deleteOnExit(); - BufferedWriter buf = new BufferedWriter(new FileWriter(confFile)); - buf.write("\n"); - if (rules != null) - { - for (RuleInfo rule : rules) - { - buf.write("\n"); - } - } - buf.write(""); - buf.close(); - - // Configure plugin - FirewallConfiguration config = new FirewallConfiguration(); - config.setConfiguration("", new XMLConfiguration(confFile)); - Firewall plugin = new Firewall(); - plugin.configure(config); - return plugin; - } - - private Firewall initialisePlugin(String string) throws ConfigurationException, IOException - { - return initialisePlugin(string, null); - } - - public void testDefaultAction() throws Exception - { - // Test simple deny - Firewall plugin = initialisePlugin("deny"); - assertEquals(Result.DENIED, plugin.access(ObjectType.VIRTUALHOST, _address)); - - // Test simple allow - plugin = initialisePlugin("allow"); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } - - - public void testSingleIPRule() throws Exception - { - RuleInfo rule = new RuleInfo(); - rule.setAccess("allow"); - rule.setNetwork("192.168.23.23"); - - Firewall plugin = initialisePlugin("deny", new RuleInfo[]{rule}); - - assertEquals(Result.DENIED, plugin.access(ObjectType.VIRTUALHOST, _address)); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("192.168.23.23", 65535); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } - - public void testSingleNetworkRule() throws Exception - { - RuleInfo rule = new RuleInfo(); - rule.setAccess("allow"); - rule.setNetwork("192.168.23.0/24"); - - Firewall plugin = initialisePlugin("deny", new RuleInfo[]{rule}); - - assertEquals(Result.DENIED, plugin.access(ObjectType.VIRTUALHOST, _address)); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("192.168.23.23", 65535); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } - - public void testSingleHostRule() throws Exception - { - RuleInfo rule = new RuleInfo(); - rule.setAccess("allow"); - rule.setHostname(new InetSocketAddress("127.0.0.1", 5672).getHostName()); - - Firewall plugin = initialisePlugin("deny", new RuleInfo[]{rule}); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("127.0.0.1", 65535); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } - - public void testSingleHostWilcardRule() throws Exception - { - RuleInfo rule = new RuleInfo(); - rule.setAccess("allow"); - String hostname = new InetSocketAddress("127.0.0.1", 0).getHostName(); - rule.setHostname(".*"+hostname.subSequence(hostname.length() - 1, hostname.length())+"*"); - Firewall plugin = initialisePlugin("deny", new RuleInfo[]{rule}); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("127.0.0.1", 65535); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } - - public void testSeveralFirstAllowsAccess() throws Exception - { - RuleInfo firstRule = new RuleInfo(); - firstRule.setAccess("allow"); - firstRule.setNetwork("192.168.23.23"); - - RuleInfo secondRule = new RuleInfo(); - secondRule.setAccess("deny"); - secondRule.setNetwork("192.168.42.42"); - - RuleInfo thirdRule = new RuleInfo(); - thirdRule.setAccess("deny"); - thirdRule.setHostname("localhost"); - - Firewall plugin = initialisePlugin("deny", new RuleInfo[]{firstRule, secondRule, thirdRule}); - - assertEquals(Result.DENIED, plugin.access(ObjectType.VIRTUALHOST, _address)); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("192.168.23.23", 65535); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } - - public void testSeveralLastAllowsAccess() throws Exception - { - RuleInfo firstRule = new RuleInfo(); - firstRule.setAccess("deny"); - firstRule.setHostname("localhost"); - - RuleInfo secondRule = new RuleInfo(); - secondRule.setAccess("deny"); - secondRule.setNetwork("192.168.42.42"); - - RuleInfo thirdRule = new RuleInfo(); - thirdRule.setAccess("allow"); - thirdRule.setNetwork("192.168.23.23"); - - Firewall plugin = initialisePlugin("deny", new RuleInfo[]{firstRule, secondRule, thirdRule}); - - assertEquals(Result.DENIED, plugin.access(ObjectType.VIRTUALHOST, _address)); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("192.168.23.23", 65535); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } - - public void testNetmask() throws Exception - { - RuleInfo firstRule = new RuleInfo(); - firstRule.setAccess("allow"); - firstRule.setNetwork("192.168.23.0/24"); - Firewall plugin = initialisePlugin("deny", new RuleInfo[]{firstRule}); - - assertEquals(Result.DENIED, plugin.access(ObjectType.VIRTUALHOST, _address)); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("192.168.23.23", 65535); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } - - public void testCommaSeperatedNetmask() throws Exception - { - RuleInfo firstRule = new RuleInfo(); - firstRule.setAccess("allow"); - firstRule.setNetwork("10.1.1.1/8, 192.168.23.0/24"); - Firewall plugin = initialisePlugin("deny", new RuleInfo[]{firstRule}); - - assertEquals(Result.DENIED, plugin.access(ObjectType.VIRTUALHOST, _address)); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("192.168.23.23", 65535); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } - - public void testCommaSeperatedHostnames() throws Exception - { - RuleInfo firstRule = new RuleInfo(); - firstRule.setAccess("allow"); - firstRule.setHostname("foo, bar, "+new InetSocketAddress("127.0.0.1", 5672).getHostName()); - Firewall plugin = initialisePlugin("deny", new RuleInfo[]{firstRule}); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("10.0.0.1", 65535); - assertEquals(Result.DENIED, plugin.access(ObjectType.VIRTUALHOST, _address)); - - // Set IP so that we're connected from the right address - _address = new InetSocketAddress("127.0.0.1", 65535); - assertEquals(Result.ALLOWED, plugin.access(ObjectType.VIRTUALHOST, _address)); - } -} diff --git a/java/broker-plugins/management-http/MANIFEST.MF b/java/broker-plugins/management-http/MANIFEST.MF deleted file mode 100644 index cca10d3f89..0000000000 --- a/java/broker-plugins/management-http/MANIFEST.MF +++ /dev/null @@ -1,70 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Qpid Broker-Plugins Management HTTP -Bundle-SymbolicName: broker-plugins-management-http -Bundle-Description: HTTP management plugin for Qpid. -Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt -Bundle-DocURL: http://www.apache.org/ -Bundle-Version: 1.0.0 -Bundle-Activator: org.apache.qpid.server.management.plugin.ManagementActivator -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ClassPath: . -Bundle-ActivationPolicy: lazy -Import-Package: org.apache.qpid, - org.apache.qpid.framing, - org.apache.qpid.protocol, - org.apache.qpid.common, - org.apache.qpid.server.security.auth, - org.apache.qpid.server.security.auth.manager, - org.apache.qpid.server.security.auth.sasl, - org.apache.qpid.server.binding, - org.apache.qpid.server.exchange, - org.apache.qpid.server.logging, - org.apache.qpid.server.message, - org.apache.qpid.server.model, - org.apache.qpid.server.model.adapter, - org.apache.qpid.server.model.impl, - org.apache.qpid.server.configuration, - org.apache.qpid.server.configuration.plugins, - org.apache.qpid.server.connection, - org.apache.qpid.server.plugins, - org.apache.qpid.server.protocol, - org.apache.qpid.server.queue, - org.apache.qpid.server.subscription, - org.apache.qpid.server.registry, - org.apache.qpid.server.security, - org.apache.qpid.server.security.access, - org.apache.qpid.server.stats, - org.apache.qpid.server.virtualhost, - org.apache.qpid.util, - org.eclipse.jetty.server;version=7.6.3, - org.eclipse.jetty.server.session;version=7.6.3, - org.eclipse.jetty.server.ssl;version=7.6.3, - org.eclipse.jetty.server.nio;version=7.6.3, - org.eclipse.jetty.security;version=7.6.3, - org.eclipse.jetty.http;version=7.6.3, - org.eclipse.jetty.io;version=7.6.3, - org.eclipse.jetty.io.nio;version=7.6.3, - org.eclipse.jetty.servlet;version=7.6.3, - org.eclipse.jetty.util.ssl;version=7.6.3, - org.apache.commons.codec;version=1.3.0, - org.apache.commons.codec.binary;version=1.3.0, - org.apache.commons.configuration;version=1.0.0, - org.apache.commons.lang;version=1.0.0, - org.apache.commons.lang.builder;version=1.0.0, - org.apache.log4j;version=1.0.0, - org.codehaus.jackson;version=1.9.0, - org.codehaus.jackson.map;version=1.9.0, - javax.crypto, - javax.crypto.spec, - javax.security.auth, - javax.security.auth.callback, - javax.security.sasl, - javax.servlet, - javax.servlet.http, - javax.management;version=1.0.0, - javax.management.openmbean;version=1.0.0, - org.osgi.util.tracker;version=1.0.0, - org.osgi.framework;version=1.3 -Private-Package: org.apache.qpid.server.management.plugin.impl -Export-Package: org.apache.qpid.server.management.plugin;uses:="org.osgi.framework" diff --git a/java/broker-plugins/management-http/build.xml b/java/broker-plugins/management-http/build.xml index b792cb292e..abf35d9c88 100644 --- a/java/broker-plugins/management-http/build.xml +++ b/java/broker-plugins/management-http/build.xml @@ -18,39 +18,36 @@ --> - - - - - - - - - - - - - - + + + + - - - - + - + - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java new file mode 100644 index 0000000000..c2ac675e20 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java @@ -0,0 +1,416 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.plugin; + +import java.io.File; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.UUID; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; +import org.apache.qpid.server.management.plugin.servlet.DefinedFileServlet; +import org.apache.qpid.server.management.plugin.servlet.FileServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.AbstractServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.LogRecordsServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.LogoutServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.MessageContentServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.MessageServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.RestServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.SaslServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.StructureServlet; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.Group; +import org.apache.qpid.server.model.GroupMember; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.KeyStore; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.Session; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.adapter.AbstractPluginAdapter; +import org.apache.qpid.server.plugin.PluginFactory; +import org.apache.qpid.server.util.MapValueConverter; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.SessionManager; +import org.eclipse.jetty.server.nio.SelectChannelConnector; +import org.eclipse.jetty.server.ssl.SslSocketConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.ssl.SslContextFactory; + +public class HttpManagement extends AbstractPluginAdapter +{ + private final Logger _logger = Logger.getLogger(HttpManagement.class); + + // 10 minutes by default + public static final int DEFAULT_TIMEOUT_IN_SECONDS = 60 * 10; + public static final boolean DEFAULT_HTTP_BASIC_AUTHENTICATION_ENABLED = false; + public static final boolean DEFAULT_HTTPS_BASIC_AUTHENTICATION_ENABLED = true; + public static final boolean DEFAULT_HTTP_SASL_AUTHENTICATION_ENABLED = true; + public static final boolean DEFAULT_HTTPS_SASL_AUTHENTICATION_ENABLED = true; + public static final String DEFAULT_NAME = "httpManagement"; + + public static final String TIME_OUT = "sessionTimeout"; + public static final String HTTP_BASIC_AUTHENTICATION_ENABLED = "httpBasicAuthenticationEnabled"; + public static final String HTTPS_BASIC_AUTHENTICATION_ENABLED = "httpsBasicAuthenticationEnabled"; + public static final String HTTP_SASL_AUTHENTICATION_ENABLED = "httpSaslAuthenticationEnabled"; + public static final String HTTPS_SASL_AUTHENTICATION_ENABLED = "httpsSaslAuthenticationEnabled"; + + public static final String PLUGIN_TYPE = "MANAGEMENT-HTTP"; + + @SuppressWarnings("serial") + private static final Collection AVAILABLE_ATTRIBUTES = Collections.unmodifiableSet(new HashSet(Plugin.AVAILABLE_ATTRIBUTES) + {{ + add(HTTP_BASIC_AUTHENTICATION_ENABLED); + add(HTTPS_BASIC_AUTHENTICATION_ENABLED); + add(HTTP_SASL_AUTHENTICATION_ENABLED); + add(HTTPS_SASL_AUTHENTICATION_ENABLED); + add(TIME_OUT); + add(PluginFactory.PLUGIN_TYPE); + }}); + + public static final String ENTRY_POINT_PATH = "/management"; + + private static final String OPERATIONAL_LOGGING_NAME = "Web"; + + + @SuppressWarnings("serial") + public static final Map DEFAULTS = Collections.unmodifiableMap(new HashMap() + {{ + put(HTTP_BASIC_AUTHENTICATION_ENABLED, DEFAULT_HTTP_BASIC_AUTHENTICATION_ENABLED); + put(HTTPS_BASIC_AUTHENTICATION_ENABLED, DEFAULT_HTTPS_BASIC_AUTHENTICATION_ENABLED); + put(HTTP_SASL_AUTHENTICATION_ENABLED, DEFAULT_HTTP_SASL_AUTHENTICATION_ENABLED); + put(HTTPS_SASL_AUTHENTICATION_ENABLED, DEFAULT_HTTPS_SASL_AUTHENTICATION_ENABLED); + put(TIME_OUT, DEFAULT_TIMEOUT_IN_SECONDS); + put(NAME, DEFAULT_NAME); + }}); + + @SuppressWarnings("serial") + private static final Map> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap>(){{ + put(HTTP_BASIC_AUTHENTICATION_ENABLED, Boolean.class); + put(HTTPS_BASIC_AUTHENTICATION_ENABLED, Boolean.class); + put(HTTP_SASL_AUTHENTICATION_ENABLED, Boolean.class); + put(HTTPS_SASL_AUTHENTICATION_ENABLED, Boolean.class); + put(NAME, String.class); + put(TIME_OUT, Integer.class); + put(PluginFactory.PLUGIN_TYPE, String.class); + }}); + + private final Broker _broker; + + private Server _server; + + public HttpManagement(UUID id, Broker broker, Map attributes) + { + super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), broker.getTaskExecutor()); + _broker = broker; + addParent(Broker.class, broker); + } + + @Override + protected boolean setState(State currentState, State desiredState) + { + if(desiredState == State.ACTIVE) + { + start(); + return true; + } + else if(desiredState == State.STOPPED) + { + stop(); + return true; + } + return false; + } + + private void start() + { + CurrentActor.get().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME)); + + Collection httpPorts = getHttpPorts(_broker.getPorts()); + _server = createServer(httpPorts); + try + { + _server.start(); + logOperationalListenMessages(_server); + } + catch (Exception e) + { + throw new RuntimeException("Failed to start http management on ports " + httpPorts); + } + + CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME)); + } + + private void stop() + { + if (_server != null) + { + try + { + _server.stop(); + logOperationalShutdownMessage(_server); + } + catch (Exception e) + { + throw new RuntimeException("Failed to stop http management on port " + getHttpPorts(_broker.getPorts())); + } + } + + CurrentActor.get().message(ManagementConsoleMessages.STOPPED(OPERATIONAL_LOGGING_NAME)); + } + + /** Added for testing purposes */ + Broker getBroker() + { + return _broker; + } + + /** Added for testing purposes */ + int getSessionTimeout() + { + return (Integer)getAttribute(TIME_OUT); + } + + private boolean isManagementHttp(Port port) + { + return port.getProtocols().contains(Protocol.HTTP) || port.getProtocols().contains(Protocol.HTTPS); + } + + @SuppressWarnings("unchecked") + private Server createServer(Collection ports) + { + if (_logger.isInfoEnabled()) + { + _logger.info("Starting up web server on " + ports); + } + + Server server = new Server(); + for (Port port : ports) + { + if (State.QUIESCED.equals(port.getActualState())) + { + continue; + } + final Collection protocols = port.getProtocols(); + Connector connector = null; + + //TODO: what to do if protocol HTTP and transport SSL? + if (protocols.contains(Protocol.HTTP)) + { + connector = new SelectChannelConnector(); + } + else if (protocols.contains(Protocol.HTTPS)) + { + KeyStore keyStore = _broker.getDefaultKeyStore(); + if (keyStore == null) + { + throw new IllegalConfigurationException("Key store is not configured. Cannot start management on HTTPS port without keystore"); + } + String keyStorePath = (String)keyStore.getAttribute(KeyStore.PATH); + String keyStorePassword = keyStore.getPassword(); + validateKeystoreParameters(keyStorePath, keyStorePassword); + + SslContextFactory factory = new SslContextFactory(); + factory.setKeyStorePath(keyStorePath); + factory.setKeyStorePassword(keyStorePassword); + + connector = new SslSocketConnector(factory); + } + else + { + throw new IllegalArgumentException("Unexpected protocol " + protocols); + } + connector.setPort(port.getPort()); + server.addConnector(connector); + } + + ServletContextHandler root = new ServletContextHandler(ServletContextHandler.SESSIONS); + root.setContextPath("/"); + server.setHandler(root); + + // set servlet context attributes for broker and configuration + root.getServletContext().setAttribute(AbstractServlet.ATTR_BROKER, _broker); + root.getServletContext().setAttribute(AbstractServlet.ATTR_MANAGEMENT, this); + + addRestServlet(root, "broker"); + addRestServlet(root, "virtualhost", VirtualHost.class); + addRestServlet(root, "authenticationprovider", AuthenticationProvider.class); + addRestServlet(root, "user", AuthenticationProvider.class, User.class); + addRestServlet(root, "groupprovider", GroupProvider.class); + addRestServlet(root, "group", GroupProvider.class, Group.class); + addRestServlet(root, "groupmember", GroupProvider.class, Group.class, GroupMember.class); + addRestServlet(root, "exchange", VirtualHost.class, Exchange.class); + addRestServlet(root, "queue", VirtualHost.class, Queue.class); + addRestServlet(root, "connection", VirtualHost.class, Connection.class); + addRestServlet(root, "binding", VirtualHost.class, Exchange.class, Queue.class, Binding.class); + addRestServlet(root, "port", Port.class); + addRestServlet(root, "session", VirtualHost.class, Connection.class, Session.class); + + root.addServlet(new ServletHolder(new StructureServlet()), "/rest/structure"); + root.addServlet(new ServletHolder(new MessageServlet()), "/rest/message/*"); + root.addServlet(new ServletHolder(new MessageContentServlet()), "/rest/message-content/*"); + + root.addServlet(new ServletHolder(new LogRecordsServlet()), "/rest/logrecords"); + + root.addServlet(new ServletHolder(new SaslServlet()), "/rest/sasl"); + + root.addServlet(new ServletHolder(new DefinedFileServlet("index.html")), ENTRY_POINT_PATH); + root.addServlet(new ServletHolder(new LogoutServlet()), "/logout"); + + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.js"); + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.css"); + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.html"); + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.png"); + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.gif"); + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpg"); + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpeg"); + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.json"); + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.txt"); + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.xsl"); + + final SessionManager sessionManager = root.getSessionHandler().getSessionManager(); + + sessionManager.setMaxInactiveInterval((Integer)getAttribute(TIME_OUT)); + + return server; + } + + private void addRestServlet(ServletContextHandler root, String name, Class... hierarchy) + { + root.addServlet(new ServletHolder(new RestServlet(hierarchy)), "/rest/" + name + "/*"); + } + + private void validateKeystoreParameters(String keyStorePath, String password) + { + if (keyStorePath == null) + { + throw new RuntimeException("Management SSL keystore path not defined, unable to start SSL protected HTTP connector"); + } + if (password == null) + { + throw new RuntimeException("Management SSL keystore password, unable to start SSL protected HTTP connector"); + } + File ksf = new File(keyStorePath); + if (!ksf.exists()) + { + throw new RuntimeException("Cannot find management SSL keystore file: " + ksf); + } + if (!ksf.canRead()) + { + throw new RuntimeException("Cannot read management SSL keystore file: " + ksf + ". Check permissions."); + } + } + + private void logOperationalListenMessages(Server server) + { + Connector[] connectors = server.getConnectors(); + for (Connector connector : connectors) + { + CurrentActor.get().message(ManagementConsoleMessages.LISTENING(stringifyConnectorScheme(connector), connector.getPort())); + if (connector instanceof SslSocketConnector) + { + SslContextFactory sslContextFactory = ((SslSocketConnector)connector).getSslContextFactory(); + if (sslContextFactory != null && sslContextFactory.getKeyStorePath() != null) + { + CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(sslContextFactory.getKeyStorePath())); + } + } + } + } + + private void logOperationalShutdownMessage(Server server) + { + Connector[] connectors = server.getConnectors(); + for (Connector connector : connectors) + { + CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN(stringifyConnectorScheme(connector), connector.getPort())); + } + } + + private String stringifyConnectorScheme(Connector connector) + { + return connector instanceof SslSocketConnector ? "HTTPS" : "HTTP"; + } + + private Collection getHttpPorts(Collection ports) + { + Collection httpPorts = new HashSet(); + for (Port port : ports) + { + if (isManagementHttp(port)) + { + httpPorts.add(port); + } + } + return httpPorts; + } + + + @Override + public String getName() + { + return (String)getAttribute(NAME); + } + + @Override + public Collection getAttributeNames() + { + return Collections.unmodifiableCollection(AVAILABLE_ATTRIBUTES); + } + + public boolean isHttpsSaslAuthenticationEnabled() + { + return (Boolean)getAttribute(HTTPS_SASL_AUTHENTICATION_ENABLED); + } + + public boolean isHttpSaslAuthenticationEnabled() + { + return (Boolean)getAttribute(HTTP_SASL_AUTHENTICATION_ENABLED); + } + + public boolean isHttpsBasicAuthenticationEnabled() + { + return (Boolean)getAttribute(HTTPS_BASIC_AUTHENTICATION_ENABLED); + } + + public boolean isHttpBasicAuthenticationEnabled() + { + return (Boolean)getAttribute(HTTP_BASIC_AUTHENTICATION_ENABLED); + } + +} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementFactory.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementFactory.java new file mode 100644 index 0000000000..ccf5373234 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementFactory.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.management.plugin; + +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.plugin.PluginFactory; + +public class HttpManagementFactory implements PluginFactory +{ + + @Override + public Plugin createInstance(UUID id, Map attributes, Broker broker) + { + if (!HttpManagement.PLUGIN_TYPE.equals(attributes.get(PLUGIN_TYPE))) + { + return null; + } + + return new HttpManagement(id, broker, attributes); + } +} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java deleted file mode 100644 index c2f9b73b54..0000000000 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/Management.java +++ /dev/null @@ -1,248 +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.management.plugin; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.server.management.plugin.servlet.DefinedFileServlet; -import org.apache.qpid.server.management.plugin.servlet.FileServlet; -import org.apache.qpid.server.management.plugin.servlet.api.ExchangesServlet; -import org.apache.qpid.server.management.plugin.servlet.api.VhostsServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.LogRecordsServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.MessageContentServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.MessageServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.RestServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.SaslServlet; -import org.apache.qpid.server.management.plugin.servlet.rest.StructureServlet; -import org.apache.qpid.server.model.AuthenticationProvider; -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.Connection; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Protocol; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.model.Session; -import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.model.User; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.SessionManager; -import org.eclipse.jetty.server.nio.SelectChannelConnector; -import org.eclipse.jetty.server.ssl.SslSocketConnector; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.ssl.SslContextFactory; - -public class Management -{ - - private final Logger _logger = Logger.getLogger(Management.class); - - private Broker _broker; - - private Collection _servers = new ArrayList(); - - public Management() throws ConfigurationException, IOException - { - _broker = ApplicationRegistry.getInstance().getBroker(); - - Collection ports = _broker.getPorts(); - int httpPort = -1, httpsPort = -1; - for (Port port : ports) - { - if (port.getProtocols().contains(Protocol.HTTP)) - { - if (port.getTransports().contains(Transport.TCP)) - { - httpPort = port.getPort(); - } - } - if (port.getProtocols().contains(Protocol.HTTPS)) - { - if (port.getTransports().contains(Transport.SSL)) - { - httpsPort = port.getPort(); - } - } - } - - if (httpPort != -1 || httpsPort != -1) - { - _servers.add(createServer(httpPort, httpsPort)); - if (_logger.isDebugEnabled()) - { - _logger.debug(_servers.size() + " server(s) defined"); - } - } - else - { - if (_logger.isInfoEnabled()) - { - _logger.info("Cannot create web server as neither HTTP nor HTTPS port specified"); - } - } - } - - @SuppressWarnings("unchecked") - private Server createServer(int port, int sslPort) throws IOException, ConfigurationException - { - if (_logger.isInfoEnabled()) - { - _logger.info("Starting up web server on" + (port == -1 ? "" : " HTTP port " + port) - + (sslPort == -1 ? "" : " HTTPS port " + sslPort)); - } - - Server server = new Server(); - - if (port != -1) - { - SelectChannelConnector connector = new SelectChannelConnector(); - connector.setPort(port); - if (sslPort != -1) - { - connector.setConfidentialPort(sslPort); - } - server.addConnector(connector); - } - - if (sslPort != -1) - { - IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); - String keyStorePath = getKeyStorePath(appRegistry); - - SslContextFactory factory = new SslContextFactory(); - factory.setKeyStorePath(keyStorePath); - factory.setKeyStorePassword(appRegistry.getConfiguration().getManagementKeyStorePassword()); - - SslSocketConnector connector = new SslSocketConnector(factory); - connector.setPort(sslPort); - server.addConnector(connector); - } - - ServletContextHandler root = new ServletContextHandler(ServletContextHandler.SESSIONS); - root.setContextPath("/"); - server.setHandler(root); - - root.addServlet(new ServletHolder(new VhostsServlet(_broker)), "/api/vhosts/*"); - root.addServlet(new ServletHolder(new ExchangesServlet(_broker)), "/api/exchanges/*"); - - addRestServlet(root, "broker"); - addRestServlet(root, "virtualhost", VirtualHost.class); - addRestServlet(root, "authenticationprovider", AuthenticationProvider.class); - addRestServlet(root, "user", AuthenticationProvider.class, User.class); - addRestServlet(root, "exchange", VirtualHost.class, Exchange.class); - addRestServlet(root, "queue", VirtualHost.class, Queue.class); - addRestServlet(root, "connection", VirtualHost.class, Connection.class); - addRestServlet(root, "binding", VirtualHost.class, Exchange.class, Queue.class, Binding.class); - addRestServlet(root, "port", Port.class); - addRestServlet(root, "session", VirtualHost.class, Connection.class, Session.class); - - root.addServlet(new ServletHolder(new StructureServlet(_broker)), "/rest/structure"); - root.addServlet(new ServletHolder(new MessageServlet(_broker)), "/rest/message/*"); - root.addServlet(new ServletHolder(new MessageContentServlet(_broker)), "/rest/message-content/*"); - - root.addServlet(new ServletHolder(new LogRecordsServlet(_broker)), "/rest/logrecords"); - - root.addServlet(new ServletHolder(new SaslServlet(_broker)), "/rest/sasl"); - - root.addServlet(new ServletHolder(new DefinedFileServlet("management.html")), "/management"); - - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.js"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.css"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.html"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.png"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.gif"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpg"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.jpeg"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.json"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.txt"); - root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.xsl"); - - final SessionManager sessionManager = root.getSessionHandler().getSessionManager(); - - sessionManager.setMaxInactiveInterval(60 * 15); - - return server; - } - - private void addRestServlet(ServletContextHandler root, String name, Class... hierarchy) - { - root.addServlet(new ServletHolder(new RestServlet(_broker, hierarchy)), "/rest/" + name + "/*"); - } - - public void start() throws Exception - { - for (Server server : _servers) - { - server.start(); - } - } - - public void stop() throws Exception - { - for (Server server : _servers) - { - server.stop(); - } - } - - private String getKeyStorePath(IApplicationRegistry appRegistry) throws ConfigurationException, FileNotFoundException - { - String keyStorePath = null; - if (System.getProperty("javax.net.ssl.keyStore") != null) - { - keyStorePath = System.getProperty("javax.net.ssl.keyStore"); - } - else - { - keyStorePath = appRegistry.getConfiguration().getManagementKeyStorePath(); - } - - if (keyStorePath == null) - { - throw new ConfigurationException("Management SSL keystore path not defined, unable to start SSL protected HTTP connector"); - } - else - { - File ksf = new File(keyStorePath); - if (!ksf.exists()) - { - throw new FileNotFoundException("Cannot find management SSL keystore file: " + ksf); - } - if (!ksf.canRead()) - { - throw new FileNotFoundException("Cannot read management SSL keystore file: " + ksf + ". Check permissions."); - } - } - return keyStorePath; - } - -} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java deleted file mode 100644 index 09b7e08bfb..0000000000 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementActivator.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.management.plugin; - -import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -public class ManagementActivator implements BundleActivator -{ - private static final Logger _logger = Logger.getLogger(ManagementActivator.class); - - - private BundleContext _ctx; - private String _bundleName; - private Management _managementService; - - - public void start(final BundleContext ctx) throws Exception - { - _ctx = ctx; - if (!ApplicationRegistry.getInstance().getConfiguration().getHTTPManagementEnabled() - && !ApplicationRegistry.getInstance().getConfiguration().getHTTPSManagementEnabled()) - { - _logger.info("Management plugin is disabled!"); - ctx.getBundle().uninstall(); - return; - } - _managementService = new Management(); - _managementService.start(); - _bundleName = ctx.getBundle().getSymbolicName(); - - // register the service - _logger.info("Registering management plugin: " + _bundleName); - _ctx.registerService(Management.class.getName(), _managementService, null); - _ctx.registerService(ConfigurationPluginFactory.class.getName(), ManagementConfiguration.FACTORY, null); - } - - public void stop(final BundleContext bundleContext) throws Exception - { - if (_managementService != null) - { - _logger.info("Stopping management plugin: " + _bundleName); - - _managementService.stop(); - - // null object references - _managementService = null; - } - _ctx = null; - } - -} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java deleted file mode 100644 index 3866da8f89..0000000000 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/ManagementConfiguration.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.management.plugin; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; - -import java.util.Arrays; -import java.util.List; - -public class ManagementConfiguration extends ConfigurationPlugin -{ - CompositeConfiguration _finalConfig; - - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - ConfigurationPlugin instance = new ManagementConfiguration(); - instance.setConfiguration(path, config); - return instance; - } - - public List getParentPaths() - { - return Arrays.asList("management"); - } - }; - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - - public Configuration getConfiguration() - { - return _finalConfig; - } - - - @Override - public void validateConfiguration() throws ConfigurationException - { - // Valid Configuration either has xml links to new files - _finalConfig = new CompositeConfiguration(getConfig()); - List subFiles = getConfig().getList("xml[@fileName]"); - for (Object subFile : subFiles) - { - _finalConfig.addConfiguration(new XMLConfiguration((String) subFile)); - } - - } - -} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java index d8a8395550..e6ae47dcff 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/DefinedFileServlet.java @@ -73,7 +73,7 @@ public class DefinedFileServlet extends HttpServlet } else { - response.sendError(404, "unknown file: "+ _filename); + response.sendError(HttpServletResponse.SC_NOT_FOUND, "unknown file: "+ _filename); } } } diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java index f8ca082d79..24e5e7c049 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java @@ -20,11 +20,8 @@ */ package org.apache.qpid.server.management.plugin.servlet; -import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; import java.util.Collections; import java.util.HashMap; @@ -101,7 +98,7 @@ public class FileServlet extends HttpServlet } else { - response.sendError(404, "unknown file: "+ filename); + response.sendError(HttpServletResponse.SC_NOT_FOUND, "unknown file: "+ filename); } } diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java deleted file mode 100644 index a3c5ec68a2..0000000000 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/ExchangesServlet.java +++ /dev/null @@ -1,208 +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.management.plugin.servlet.api; - -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.map.ObjectReader; - -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.registry.ApplicationRegistry; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -public class ExchangesServlet extends HttpServlet -{ - - - private Broker _broker; - - public ExchangesServlet() - { - super(); - _broker = ApplicationRegistry.getInstance().getBroker(); - } - - public ExchangesServlet(Broker broker) - { - _broker = broker; - } - - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_OK); - - Collection vhosts = _broker.getVirtualHosts(); - Collection exchanges = new ArrayList(); - Collection> outputObject = new ArrayList>(); - - final PrintWriter writer = response.getWriter(); - - ObjectMapper mapper = new ObjectMapper(); - String vhostName = null; - String exchangeName = null; - - if(request.getPathInfo() != null && request.getPathInfo().length()>0) - { - String path = request.getPathInfo().substring(1); - String[] parts = path.split("/"); - vhostName = parts.length == 0 ? "" : parts[0]; - if(parts.length > 1) - { - exchangeName = parts[1]; - } - } - - for(VirtualHost vhost : vhosts) - { - if(vhostName == null || vhostName.equals(vhost.getName())) - { - for(Exchange exchange : vhost.getExchanges()) - { - if(exchangeName == null || exchangeName.equals(exchange.getName())) - { - outputObject.add(convertToObject(exchange)); - if(exchangeName != null) - { - break; - } - } - } - if(vhostName != null) - { - break; - } - } - } - - mapper.writeValue(writer, outputObject); - - } - - private Map convertToObject(final Exchange exchange) - { - Map object = new LinkedHashMap(); - object.put("name",exchange.getName()); - object.put("type", exchange.getExchangeType()); - object.put("durable", exchange.isDurable()); - object.put("auto-delete", exchange.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE); - - Map arguments = new HashMap(); - for(String key : exchange.getAttributeNames()) - { - if(!key.equals(Exchange.TYPE)) - { - arguments.put(key, exchange.getAttribute(key)); - } - } - object.put("arguments", arguments); - return object; - } - - protected void doPut(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException - { - - response.setContentType("application/json"); - - - String vhostName = null; - String exchangeName = null; - if(request.getPathInfo() != null && request.getPathInfo().length()>0) - { - String path = request.getPathInfo().substring(1); - String[] parts = path.split("/"); - vhostName = parts.length == 0 ? "" : parts[0]; - if(parts.length > 1) - { - exchangeName = parts[1]; - } - } - if(vhostName == null) - { - response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); - } - else if (exchangeName == null) - { - response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); - } - else - { - VirtualHost vhost = null; - for(VirtualHost host : _broker.getVirtualHosts()) - { - if(host.getName().equals(vhostName)) - { - vhost = host; - } - } - if(vhost == null) - { - response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED); - } - else - { - response.setStatus(HttpServletResponse.SC_NO_CONTENT); - ObjectMapper mapper = new ObjectMapper(); - Map exchangeObject = mapper.readValue(request.getInputStream(), LinkedHashMap.class); - - final boolean isDurable = exchangeObject.get("durable") instanceof Boolean - && ((Boolean)exchangeObject.get("durable")); - final boolean isAutoDelete = exchangeObject.get("auto_delete") instanceof Boolean - && ((Boolean)exchangeObject.get("auto_delete")); - - final String type = (String) exchangeObject.get("type"); - final Map attributes = new HashMap(exchangeObject); - attributes.remove("durable"); - attributes.remove("auto_delete"); - attributes.remove("type"); - - vhost.createExchange(exchangeName, State.ACTIVE, isDurable, - isAutoDelete ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT, - 0l, - type, - attributes); - } - - - - } - - - - } -} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java deleted file mode 100644 index b2c0fcfe52..0000000000 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/api/VhostsServlet.java +++ /dev/null @@ -1,118 +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.management.plugin.servlet.api; - -import org.codehaus.jackson.map.ObjectMapper; - -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.registry.ApplicationRegistry; - - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.*; - -public class VhostsServlet extends HttpServlet -{ - - - private Broker _broker; - - public VhostsServlet() - { - super(); - _broker = ApplicationRegistry.getInstance().getBroker(); - } - - public VhostsServlet(Broker broker) - { - _broker = broker; - } - - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { -System.out.println("Get /api/vhosts"); - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_OK); - - Collection vhosts = _broker.getVirtualHosts(); - - - - final PrintWriter writer = response.getWriter(); - - ObjectMapper mapper = new ObjectMapper(); - - if(request.getPathInfo() == null || request.getPathInfo().length()==0) - { - - LinkedHashMap vhostObject = new LinkedHashMap(); - List vhostList = new ArrayList(); - - for(VirtualHost vhost : vhosts) - { - vhostList.add(Collections.singletonMap("name", vhost.getName())); - } - mapper.writeValue(writer, vhostList); - } - else - { - LinkedHashMap vhostObject = new LinkedHashMap(); - String vhostName = request.getPathInfo().substring(1); - - for(VirtualHost vhost : vhosts) - { - if(vhostName.equals(vhost.getName())) - { - vhostObject.put("name", vhost.getName()); - break; - } - } - mapper.writeValue(writer, vhostObject); - } - } - - - protected void doPut(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException - { - - response.setContentType("application/json"); - response.setStatus(HttpServletResponse.SC_NO_CONTENT); - - if(request.getPathInfo() != null && request.getPathInfo().length()>0) - { - String vhostName = request.getPathInfo().substring(1); - _broker.createVirtualHost(vhostName, State.ACTIVE, true, LifetimePolicy.PERMANENT, 0L, Collections.EMPTY_MAP); - } - - - } -} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java index a76bd98179..689bdb50d8 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java @@ -18,191 +18,456 @@ * under the License. * */ - package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.security.Principal; -import java.util.Collections; +import java.security.AccessControlException; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + import javax.security.auth.Subject; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.HttpManagementActor; +import org.apache.qpid.server.management.plugin.HttpManagement; +import org.apache.qpid.server.management.plugin.session.LoginLogoutReporter; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; public abstract class AbstractServlet extends HttpServlet { - private final Broker _broker; + private static final Logger LOGGER = Logger.getLogger(AbstractServlet.class); + + /** + * Servlet context attribute holding a reference to a broker instance + */ + public static final String ATTR_BROKER = "Qpid.broker"; + + /** + * Servlet context attribute holding a reference to plugin configuration + */ + public static final String ATTR_MANAGEMENT = "Qpid.management"; + + private static final String ATTR_LOGIN_LOGOUT_REPORTER = "AbstractServlet.loginLogoutReporter"; + private static final String ATTR_SUBJECT = "AbstractServlet.subject"; + private static final String ATTR_LOG_ACTOR = "AbstractServlet.logActor"; + + private Broker _broker; + private RootMessageLogger _rootLogger; + private HttpManagement _httpManagement; protected AbstractServlet() { super(); - _broker = ApplicationRegistry.getInstance().getBroker(); } - protected AbstractServlet(Broker broker) + @Override + public void init() throws ServletException { - _broker = broker; + ServletConfig servletConfig = getServletConfig(); + ServletContext servletContext = servletConfig.getServletContext(); + _broker = (Broker)servletContext.getAttribute(ATTR_BROKER); + _rootLogger = _broker.getRootMessageLogger(); + _httpManagement = (HttpManagement)servletContext.getAttribute(ATTR_MANAGEMENT); + super.init(); } @Override - protected final void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException + protected final void doGet(final HttpServletRequest request, final HttpServletResponse resp) { - setAuthorizedSubject(request); - try - { - onGet(request, resp); - } - finally - { - clearAuthorizedSubject(); - } + doWithSubjectAndActor( + new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + doGetWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); + } + + /** + * Performs the GET action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException + { + throw new UnsupportedOperationException("GET not supported by this servlet"); + } + + + @Override + protected final void doPost(final HttpServletRequest request, final HttpServletResponse resp) + { + doWithSubjectAndActor( + new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + doPostWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); + } + + /** + * Performs the POST action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doPostWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + throw new UnsupportedOperationException("POST not supported by this servlet"); + } + + @Override + protected final void doPut(final HttpServletRequest request, final HttpServletResponse resp) + { + doWithSubjectAndActor( + new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + doPutWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); } - protected void onGet(HttpServletRequest request, HttpServletResponse resp) throws IOException, ServletException + /** + * Performs the PUT action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doPutWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doGet(request, resp); + throw new UnsupportedOperationException("PUT not supported by this servlet"); } - private void clearAuthorizedSubject() + @Override + protected final void doDelete(final HttpServletRequest request, final HttpServletResponse resp) + throws ServletException, IOException { - org.apache.qpid.server.security.SecurityManager.setThreadSubject(null); + doWithSubjectAndActor( + new PrivilegedExceptionAction() + { + @Override + public Void run() throws Exception + { + doDeleteWithSubjectAndActor(request, resp); + return null; + } + }, + request, + resp + ); } + /** + * Performs the PUT action as the logged-in {@link Subject}. + * The {@link LogActor} is set before this method is called. + * Subclasses commonly override this method + */ + protected void doDeleteWithSubjectAndActor(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + throw new UnsupportedOperationException("DELETE not supported by this servlet"); + } - private void setAuthorizedSubject(HttpServletRequest request) + private void doWithSubjectAndActor( + PrivilegedExceptionAction privilegedExceptionAction, + final HttpServletRequest request, + final HttpServletResponse resp) { - HttpSession session = request.getSession(true); - Subject subject = (Subject) session.getAttribute("subject"); + Subject subject; + try + { + subject = getAndCacheAuthorizedSubject(request); + } + catch (AccessControlException e) + { + sendError(resp, HttpServletResponse.SC_FORBIDDEN); + return; + } - if(subject == null) + SecurityManager.setThreadSubject(subject); + try { - Principal principal = request.getUserPrincipal(); - if(principal != null) + HttpManagementActor logActor = getLogActorAndCacheInSession(request); + CurrentActor.set(logActor); + try + { + Subject.doAs(subject, privilegedExceptionAction); + } + catch(RuntimeException e) { - subject = new Subject(false, Collections.singleton(principal),Collections.emptySet(), - Collections.emptySet()); + LOGGER.error("Unable to perform action", e); + throw e; } - else + catch (PrivilegedActionException e) { - String header = request.getHeader("Authorization"); + LOGGER.error("Unable to perform action", e); + throw new RuntimeException(e.getCause()); + } + finally + { + CurrentActor.remove(); + } + } + finally + { + try + { + SecurityManager.setThreadSubject(null); + } + finally + { + AMQShortString.clearLocalCache(); + } + } + } + + /** + * Gets the logged-in {@link Subject} by trying the following: + * + *

    + *
  • Get it from the session
  • + *
  • Get it from the request
  • + *
  • Log in using the username and password in the Authorization HTTP header
  • + *
  • Create a Subject representing the anonymous user.
  • + *
+ * + * If an authenticated subject is found it is cached in the http session. + */ + private Subject getAndCacheAuthorizedSubject(HttpServletRequest request) + { + HttpSession session = request.getSession(); + Subject subject = getAuthorisedSubjectFromSession(session); - /* - * TODO - Should configure whether basic authentication is allowed... and in particular whether it - * should be allowed over non-ssl connections - * */ + if(subject != null) + { + return subject; + } - if (header != null) + SubjectCreator subjectCreator = getSubjectCreator(request); + subject = authenticate(request, subjectCreator); + if (subject != null) + { + authoriseManagement(request, subject); + setAuthorisedSubjectInSession(subject, request, session); + } + else + { + subject = subjectCreator.createSubjectWithGroups(AnonymousAuthenticationManager.ANONYMOUS_USERNAME); + } + + return subject; + } + + protected void authoriseManagement(HttpServletRequest request, Subject subject) + { + // TODO: We should eliminate SecurityManager.setThreadSubject in favour of Subject.doAs + SecurityManager.setThreadSubject(subject); // Required for accessManagement check + LogActor actor = createHttpManagementActor(request); + CurrentActor.set(actor); + try + { + try + { + Subject.doAs(subject, new PrivilegedExceptionAction() // Required for proper logging of Subject { - String[] tokens = header.split("\\s"); - if(tokens.length >= 2 - && "BASIC".equalsIgnoreCase(tokens[0])) + @Override + public Void run() throws Exception { - String[] credentials = (new String(Base64.decodeBase64(tokens[1].getBytes()))).split(":",2); - if(credentials.length == 2) + boolean allowed = getSecurityManager().accessManagement(); + if (!allowed) { - SocketAddress address = getSocketAddress(request); - AuthenticationManager authenticationManager = - ApplicationRegistry.getInstance().getAuthenticationManager(address); - AuthenticationResult authResult = - authenticationManager.authenticate(credentials[0], credentials[1]); - subject = authResult.getSubject(); - + throw new AccessControlException("User is not authorised for management"); } + return null; } - } + }); + } + catch (PrivilegedActionException e) + { + throw new RuntimeException("Unable to perform access check", e); } } - if (subject == null) + finally { - subject = AnonymousAuthenticationManager.ANONYMOUS_SUBJECT; + try + { + CurrentActor.remove(); + } + finally + { + SecurityManager.setThreadSubject(null); + } } - org.apache.qpid.server.security.SecurityManager.setThreadSubject(subject); - } - protected Subject getSubject(HttpSession session) + private Subject authenticate(HttpServletRequest request, SubjectCreator subjectCreator) { - return (Subject)session.getAttribute("subject"); + Subject subject = null; + + String remoteUser = request.getRemoteUser(); + if(remoteUser != null) + { + subject = authenticateUserAndGetSubject(subjectCreator, remoteUser, null); + } + else + { + String header = request.getHeader("Authorization"); + + if (header != null) + { + String[] tokens = header.split("\\s"); + if(tokens.length >= 2 && "BASIC".equalsIgnoreCase(tokens[0])) + { + if(!isBasicAuthSupported(request)) + { + //TODO: write a return response indicating failure? + throw new IllegalArgumentException("BASIC Authorization is not enabled."); + } + + subject = performBasicAuth(subject, subjectCreator, tokens[1]); + } + } + } + + return subject; } - @Override - protected final void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + private Subject performBasicAuth(Subject subject,SubjectCreator subjectCreator, String base64UsernameAndPassword) { - setAuthorizedSubject(req); - try + String[] credentials = (new String(Base64.decodeBase64(base64UsernameAndPassword.getBytes()))).split(":",2); + if(credentials.length == 2) { - onPost(req, resp); + subject = authenticateUserAndGetSubject(subjectCreator, credentials[0], credentials[1]); } - finally + else { - clearAuthorizedSubject(); + //TODO: write a return response indicating failure? + throw new AccessControlException("Invalid number of credentials supplied: " + + credentials.length); } + return subject; + } + private Subject authenticateUserAndGetSubject(SubjectCreator subjectCreator, String username, String password) + { + SubjectAuthenticationResult authResult = subjectCreator.authenticate(username, password); + if( authResult.getStatus() != AuthenticationStatus.SUCCESS) + { + //TODO: write a return response indicating failure? + throw new AccessControlException("Incorrect username or password"); + } + Subject subject = authResult.getSubject(); + return subject; } - protected void onPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + private boolean isBasicAuthSupported(HttpServletRequest req) { - super.doPost(req, resp); + return req.isSecure() ? _httpManagement.isHttpsBasicAuthenticationEnabled() + : _httpManagement.isHttpBasicAuthenticationEnabled(); } - @Override - protected final void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + private HttpManagementActor getLogActorAndCacheInSession(HttpServletRequest req) { - setAuthorizedSubject(req); - try - { - onPut(req, resp); + HttpSession session = req.getSession(); - } - finally + HttpManagementActor actor = (HttpManagementActor) session.getAttribute(ATTR_LOG_ACTOR); + if(actor == null) { - clearAuthorizedSubject(); + actor = createHttpManagementActor(req); + session.setAttribute(ATTR_LOG_ACTOR, actor); } + + return actor; } - protected void onPut(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException + protected Subject getAuthorisedSubjectFromSession(HttpSession session) { - super.doPut(req,resp); + return (Subject)session.getAttribute(ATTR_SUBJECT); } - @Override - protected final void doDelete(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException + protected void setAuthorisedSubjectInSession(Subject subject, HttpServletRequest request, final HttpSession session) + { + session.setAttribute(ATTR_SUBJECT, subject); + + LogActor logActor = createHttpManagementActor(request); + // Cause the user logon to be logged. + session.setAttribute(ATTR_LOGIN_LOGOUT_REPORTER, new LoginLogoutReporter(logActor, subject)); + } + + protected Broker getBroker() + { + return _broker; + } + + protected SocketAddress getSocketAddress(HttpServletRequest request) + { + return InetSocketAddress.createUnresolved(request.getServerName(), request.getServerPort()); + } + + protected void sendError(final HttpServletResponse resp, int errorCode) { - setAuthorizedSubject(req); try { - onDelete(req, resp); + resp.sendError(errorCode); } - finally + catch (IOException e) { - clearAuthorizedSubject(); + throw new RuntimeException("Failed to send error response code " + errorCode, e); } } - protected void onDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + private HttpManagementActor createHttpManagementActor(HttpServletRequest request) { - super.doDelete(req, resp); + return new HttpManagementActor(_rootLogger, request.getRemoteAddr(), request.getRemotePort()); } + protected HttpManagement getManagement() + { + return _httpManagement; + } - protected Broker getBroker() + protected SecurityManager getSecurityManager() { - return _broker; + return _broker.getSecurityManager(); } - protected SocketAddress getSocketAddress(HttpServletRequest request) + protected SubjectCreator getSubjectCreator(HttpServletRequest request) { - return InetSocketAddress.createUnresolved(request.getServerName(), request.getServerPort()); + return _broker.getSubjectCreator(getSocketAddress(request)); } } diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java index 404793b592..f2cf5d7734 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java @@ -26,8 +26,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.qpid.server.logging.LogRecorder; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; @@ -35,16 +33,11 @@ public class LogRecordsServlet extends AbstractServlet { public LogRecordsServlet() { - super(ApplicationRegistry.getInstance().getBroker()); - } - - public LogRecordsServlet(Broker broker) - { - super(broker); + super(); } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); @@ -53,10 +46,10 @@ public class LogRecordsServlet extends AbstractServlet response.setHeader("Pragma","no-cache"); response.setDateHeader ("Expires", 0); - ApplicationRegistry applicationRegistry = (ApplicationRegistry) ApplicationRegistry.getInstance(); List> logRecords = new ArrayList>(); - for(LogRecorder.Record record : applicationRegistry.getLogRecorder()) + LogRecorder logRecorder = getBroker().getLogRecorder(); + for(LogRecorder.Record record : logRecorder) { logRecords.add(logRecordToObject(record)); } diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogoutServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogoutServlet.java new file mode 100644 index 0000000000..4188e7d60d --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogoutServlet.java @@ -0,0 +1,65 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.qpid.server.management.plugin.HttpManagement; + +@SuppressWarnings("serial") +public class LogoutServlet extends HttpServlet +{ + public static final String RETURN_URL_INIT_PARAM = "qpid.webui_logout_redirect"; + private String _returnUrl = HttpManagement.ENTRY_POINT_PATH; + + @Override + public void init(ServletConfig config) throws ServletException + { + super.init(config); + + String initValue = config.getServletContext().getInitParameter(RETURN_URL_INIT_PARAM); + if(initValue != null) + { + _returnUrl = initValue; + } + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse resp) throws ServletException, IOException + { + HttpSession session = request.getSession(false); + if(session != null) + { + // Invalidating the session will cause LoginLogoutReporter to log the user logoff. + session.invalidate(); + } + + resp.sendRedirect(_returnUrl); + } + +} diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java index bc87f0bcc5..d61c48bb2c 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java @@ -29,7 +29,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.queue.QueueEntry; @@ -42,13 +41,8 @@ public class MessageContentServlet extends AbstractServlet super(); } - public MessageContentServlet(Broker broker) - { - super(broker); - } - @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2) diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java index 6e7bc1d935..49e0c2b1bf 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java @@ -34,13 +34,10 @@ import org.apache.log4j.Logger; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.queue.QueueEntryVisitor; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.subscription.Subscription; @@ -56,13 +53,8 @@ public class MessageServlet extends AbstractServlet super(); } - public MessageServlet(Broker broker) - { - super(broker); - } - @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { if(request.getPathInfo() != null && request.getPathInfo().length()>0 && request.getPathInfo().substring(1).split("/").length > 2) @@ -400,7 +392,7 @@ public class MessageServlet extends AbstractServlet * POST moves or copies messages to the given queue from a queue specified in the posted JSON data */ @Override - protected void onPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doPostWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try @@ -422,7 +414,7 @@ public class MessageServlet extends AbstractServlet // FIXME: added temporary authorization check until we introduce management layer // and review current ACL rules to have common rules for all management interfaces String methodName = isMoveTransaction? "moveMessages":"copyMessages"; - if (isQueueUpdateMethodAuthorized(methodName, vhost.getName())) + if (isQueueUpdateMethodAuthorized(methodName, vhost)) { final Queue destinationQueue = getQueueFromVirtualHost(destQueueName, vhost); final List messageIds = new ArrayList((List) providedObject.get("messages")); @@ -435,7 +427,7 @@ public class MessageServlet extends AbstractServlet } else { - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); } } catch(RuntimeException e) @@ -450,7 +442,7 @@ public class MessageServlet extends AbstractServlet * DELETE removes messages from the queue */ @Override - protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) { final Queue sourceQueue = getQueueFromRequest(request); @@ -466,37 +458,22 @@ public class MessageServlet extends AbstractServlet // FIXME: added temporary authorization check until we introduce management layer // and review current ACL rules to have common rules for all management interfaces - if (isQueueUpdateMethodAuthorized("deleteMessages", vhost.getName())) + if (isQueueUpdateMethodAuthorized("deleteMessages", vhost)) { vhost.executeTransaction(new DeleteTransaction(sourceQueue, messageIds)); response.setStatus(HttpServletResponse.SC_OK); } else { - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); } } - private boolean isQueueUpdateMethodAuthorized(String methodName, String virtualHost) + private boolean isQueueUpdateMethodAuthorized(String methodName, VirtualHost host) { - SecurityManager securityManager = getSecurityManager(virtualHost); + SecurityManager securityManager = host.getSecurityManager(); return securityManager.authoriseMethod(Operation.UPDATE, "VirtualHost.Queue", methodName); } - private SecurityManager getSecurityManager(String virtualHost) - { - IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); - SecurityManager security; - if (virtualHost == null) - { - security = appRegistry.getSecurityManager(); - } - else - { - security = appRegistry.getVirtualHostRegistry().getVirtualHost(virtualHost).getSecurityManager(); - } - return security; - } - } diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java index 6a79916d07..3fab26cde5 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java @@ -19,6 +19,7 @@ package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.BufferedWriter; import java.io.IOException; import java.io.Writer; +import java.security.AccessControlException; import java.util.*; import javax.servlet.ServletConfig; import javax.servlet.ServletException; @@ -31,7 +32,6 @@ import org.apache.qpid.server.model.*; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; - public class RestServlet extends AbstractServlet { private static final Logger LOGGER = Logger.getLogger(RestServlet.class); @@ -47,29 +47,29 @@ public class RestServlet extends AbstractServlet private Class[] _hierarchy; - private volatile boolean initializationRequired = false; - private final ConfiguredObjectToMapConverter _objectConverter = new ConfiguredObjectToMapConverter(); + private final boolean _hierarchyInitializationRequired; public RestServlet() { super(); - initializationRequired = true; + _hierarchyInitializationRequired = true; } - public RestServlet(Broker broker, Class... hierarchy) + public RestServlet(Class... hierarchy) { - super(broker); + super(); _hierarchy = hierarchy; + _hierarchyInitializationRequired = false; } @Override public void init() throws ServletException { - if (initializationRequired) + super.init(); + if (_hierarchyInitializationRequired) { doInitialization(); - initializationRequired = false; } } @@ -285,7 +285,7 @@ public class RestServlet extends AbstractServlet } @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); @@ -319,7 +319,7 @@ public class RestServlet extends AbstractServlet } @Override - protected void onPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doPutWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); @@ -336,7 +336,8 @@ public class RestServlet extends AbstractServlet if(names.size() != _hierarchy.length) { - throw new IllegalArgumentException("Path to object to create must be fully specified"); + throw new IllegalArgumentException("Path to object to create must be fully specified. " + + "Found " + names.size() + " expecting " + _hierarchy.length); } } @@ -428,8 +429,11 @@ public class RestServlet extends AbstractServlet || (obj.getName().equals(providedObject.get("name")) && equalParents(obj, otherParents))) { doUpdate(obj, providedObject); + response.setStatus(HttpServletResponse.SC_OK); + return; } } + theParent.createChild(objClass, providedObject, otherParents); } catch (RuntimeException e) @@ -462,13 +466,17 @@ public class RestServlet extends AbstractServlet private void setResponseStatus(HttpServletResponse response, RuntimeException e) throws IOException { - if (e.getCause() instanceof AMQSecurityException) + if (e instanceof AccessControlException || e.getCause() instanceof AMQSecurityException) { - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Caught security exception, sending " + HttpServletResponse.SC_FORBIDDEN, e); + } + response.setStatus(HttpServletResponse.SC_FORBIDDEN); } else { - LOGGER.warn("Unexpected exception is caught", e); + LOGGER.warn("Caught exception", e); // TODO response.setStatus(HttpServletResponse.SC_CONFLICT); @@ -476,7 +484,7 @@ public class RestServlet extends AbstractServlet } @Override - protected void onDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java index 1b78611a50..069132af1e 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java @@ -25,10 +25,9 @@ import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; import org.apache.log4j.Logger; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.management.plugin.HttpManagement; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import javax.security.auth.Subject; import javax.security.sasl.SaslException; @@ -39,6 +38,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter; +import java.security.AccessControlException; import java.security.Principal; import java.security.SecureRandom; import java.util.LinkedHashMap; @@ -47,6 +47,7 @@ import java.util.Random; public class SaslServlet extends AbstractServlet { + private static final Logger LOGGER = Logger.getLogger(SaslServlet.class); private static final SecureRandom SECURE_RANDOM = new SecureRandom(); @@ -56,18 +57,12 @@ public class SaslServlet extends AbstractServlet private static final String ATTR_EXPIRY = "SaslServlet.Expiry"; private static final long SASL_EXCHANGE_EXPIRY = 1000L; - public SaslServlet() { super(); } - public SaslServlet(Broker broker) - { - super(broker); - } - - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { @@ -79,15 +74,16 @@ public class SaslServlet extends AbstractServlet response.setDateHeader ("Expires", 0); HttpSession session = request.getSession(); - Random rand = getRandom(session); + getRandom(session); - AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request)); - String[] mechanisms = authManager.getMechanisms().split(" "); + SubjectCreator subjectCreator = getSubjectCreator(request); + String[] mechanisms = subjectCreator.getMechanisms().split(" "); Map outputObject = new LinkedHashMap(); - final Subject subject = (Subject) session.getAttribute("subject"); + + final Subject subject = getAuthorisedSubjectFromSession(session); if(subject != null) { - final Principal principal = subject.getPrincipals().iterator().next(); + Principal principal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); outputObject.put("user", principal.getName()); } else if (request.getRemoteUser() != null) @@ -121,9 +117,10 @@ public class SaslServlet extends AbstractServlet @Override - protected void onPost(final HttpServletRequest request, final HttpServletResponse response) - throws ServletException, IOException + protected void doPostWithSubjectAndActor(final HttpServletRequest request, final HttpServletResponse response) throws IOException { + checkSaslAuthEnabled(request); + try { response.setContentType("application/json"); @@ -137,14 +134,18 @@ public class SaslServlet extends AbstractServlet String id = request.getParameter("id"); String saslResponse = request.getParameter("response"); - AuthenticationManager authManager = ApplicationRegistry.getInstance().getAuthenticationManager(getSocketAddress(request)); + SubjectCreator subjectCreator = getSubjectCreator(request); if(mechanism != null) { if(id == null) { - SaslServer saslServer = authManager.createSaslServer(mechanism, request.getServerName(), null/*TODO*/); - evaluateSaslResponse(response, session, saslResponse, saslServer); + if(LOGGER.isDebugEnabled()) + { + LOGGER.debug("Creating SaslServer for mechanism: " + mechanism); + } + SaslServer saslServer = subjectCreator.createSaslServer(mechanism, request.getServerName(), null/*TODO*/); + evaluateSaslResponse(request, response, session, saslResponse, saslServer, subjectCreator); } else { @@ -152,9 +153,7 @@ public class SaslServlet extends AbstractServlet session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); - } - } else { @@ -163,8 +162,7 @@ public class SaslServlet extends AbstractServlet if(id.equals(session.getAttribute(ATTR_ID)) && System.currentTimeMillis() < (Long) session.getAttribute(ATTR_EXPIRY)) { SaslServer saslServer = (SaslServer) session.getAttribute(ATTR_SASL_SERVER); - evaluateSaslResponse(response, session, saslResponse, saslServer); - + evaluateSaslResponse(request, response, session, saslResponse, saslServer, subjectCreator); } else { @@ -180,7 +178,6 @@ public class SaslServlet extends AbstractServlet session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); - } } } @@ -194,12 +191,30 @@ public class SaslServlet extends AbstractServlet LOGGER.error("Error processing SASL request", e); throw e; } + } + private void checkSaslAuthEnabled(HttpServletRequest request) + { + boolean saslAuthEnabled; + HttpManagement management = getManagement(); + if (request.isSecure()) + { + saslAuthEnabled = management.isHttpsSaslAuthenticationEnabled(); + } + else + { + saslAuthEnabled = management.isHttpSaslAuthenticationEnabled(); + } + + if (!saslAuthEnabled) + { + throw new RuntimeException("Sasl authentication disabled."); + } } - private void evaluateSaslResponse(final HttpServletResponse response, - final HttpSession session, - final String saslResponse, final SaslServer saslServer) throws IOException + private void evaluateSaslResponse(final HttpServletRequest request, + final HttpServletResponse response, + final HttpSession session, final String saslResponse, final SaslServer saslServer, SubjectCreator subjectCreator) throws IOException { final String id; byte[] challenge; @@ -209,27 +224,34 @@ public class SaslServlet extends AbstractServlet } catch(SaslException e) { - session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); return; } if(saslServer.isComplete()) { - final Subject subject = new Subject(); - subject.getPrincipals().add(new UsernamePrincipal(saslServer.getAuthorizationID())); - session.setAttribute("subject", subject); + Subject subject = subjectCreator.createSubjectWithGroups(saslServer.getAuthorizationID()); + + try + { + authoriseManagement(request, subject); + } + catch (AccessControlException ace) + { + sendError(response, HttpServletResponse.SC_FORBIDDEN); + return; + } + + setAuthorisedSubjectInSession(subject, request, session); session.removeAttribute(ATTR_ID); session.removeAttribute(ATTR_SASL_SERVER); session.removeAttribute(ATTR_EXPIRY); response.setStatus(HttpServletResponse.SC_OK); - - } else { @@ -250,7 +272,6 @@ public class SaslServlet extends AbstractServlet ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); mapper.writeValue(writer, outputObject); - } } } diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java index 60f977ca66..40d3c02768 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureServlet.java @@ -41,13 +41,8 @@ public class StructureServlet extends AbstractServlet super(); } - public StructureServlet(Broker broker) - { - super(broker); - } - @Override - protected void onGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_OK); @@ -56,6 +51,8 @@ public class StructureServlet extends AbstractServlet response.setHeader("Pragma","no-cache"); response.setDateHeader ("Expires", 0); + // TODO filtering??? request.getParameter("filter"); // filter=1,2,3 /groups/*/* + Map structure = generateStructure(getBroker(), Broker.class); final PrintWriter writer = response.getWriter(); diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/session/LoginLogoutReporter.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/session/LoginLogoutReporter.java new file mode 100644 index 0000000000..238f1b4719 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/session/LoginLogoutReporter.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.session; + +import java.security.Principal; +import java.security.PrivilegedAction; + +import javax.security.auth.Subject; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionBindingEvent; +import javax.servlet.http.HttpSessionBindingListener; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; + +/** + * Logs {@link ManagementConsoleMessages#OPEN(String)} and {@link ManagementConsoleMessages#CLOSE(String)} + * messages. A single instance of this class must be placed in the {@link HttpSession} immediately after + * the user has successfully logged-in, and removed (or the whole session invalidated) as the user logs out. + */ +public class LoginLogoutReporter implements HttpSessionBindingListener +{ + private static final Logger LOGGER = Logger.getLogger(LoginLogoutReporter.class); + private final LogActor _logActor; + private final Subject _subject; + private final Principal _principal; + + public LoginLogoutReporter(LogActor logActor, Subject subject) + { + super(); + _logActor = logActor; + _subject = subject; + _principal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(_subject); + } + + @Override + public void valueBound(HttpSessionBindingEvent arg0) + { + reportLogin(); + } + + @Override + public void valueUnbound(HttpSessionBindingEvent arg0) + { + reportLogout(); + } + + private void reportLogin() + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("User logging in : " + _principal); + } + + Subject.doAs(_subject, new PrivilegedAction() + { + @Override + public Void run() + { + _logActor.message(ManagementConsoleMessages.OPEN(_principal.getName())); + return null; + } + }); + } + + private void reportLogout() + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("User logging out : " + _principal); + } + + Subject.doAs(_subject, new PrivilegedAction() + { + @Override + public Void run() + { + _logActor.message(ManagementConsoleMessages.CLOSE(_principal.getName())); + return null; + } + }); + } + +} diff --git a/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html index baadc8c35f..e6c067fddf 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html +++ b/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/showPrincipalDatabaseAuthenticationManager.html @@ -23,7 +23,5 @@
- - diff --git a/java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html b/java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html new file mode 100644 index 0000000000..0372468f91 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/group/addGroupMember.html @@ -0,0 +1,37 @@ + +
+
+
+ + + + + +
Name*:
+
+ + + +
+
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html b/java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html new file mode 100644 index 0000000000..4fddf727d0 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/group/showGroup.html @@ -0,0 +1,30 @@ + +
+ Name: +
+
+
+ + +
+
+ diff --git a/java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html b/java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html new file mode 100644 index 0000000000..8d3431808a --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/groupprovider/addGroup.html @@ -0,0 +1,38 @@ + +
+
+
+ + + + + +
Group Name*:
+
+ + + + +
+
+
diff --git a/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html b/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html new file mode 100644 index 0000000000..734e8b5419 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/groupprovider/showFileGroupManager.html @@ -0,0 +1,28 @@ + +
+
+
+ + +
+ +
diff --git a/java/broker-plugins/management-http/src/main/java/resources/index.html b/java/broker-plugins/management-http/src/main/java/resources/index.html new file mode 100644 index 0000000000..2fb9137ff8 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/index.html @@ -0,0 +1,90 @@ + + + + + + Qpid Management + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js index 152504da86..b4f0728685 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js @@ -71,7 +71,7 @@ var saslPlain = function saslPlain(user, password) }, function(error) { - if(error.status == 401) + if(error.status == 403) { alert("Authentication Failed"); } @@ -127,7 +127,7 @@ var saslCramMD5 = function saslCramMD5(user, password) }, function(error) { - if(error.status == 401) + if(error.status == 403) { alert("Authentication Failed"); } @@ -141,7 +141,7 @@ var saslCramMD5 = function saslCramMD5(user, password) }, function(error) { - if(error.status == 401) + if(error.status == 403) { alert("Authentication Failed"); } @@ -152,10 +152,45 @@ var saslCramMD5 = function saslCramMD5(user, password) }); }; +var containsMechanism = function containsMechanism(mechanisms, mech) +{ + for (var i = 0; i < mechanisms.length; i++) { + if (mechanisms[i] == mech) { + return true; + } + } + + return false; +}; + var doAuthenticate = function doAuthenticate() { - saslCramMD5(dojo.byId("username").value, dojo.byId("pass").value); - updateAuthentication(); + dojo.xhrGet({ + // The URL of the request + url: "rest/sasl", + handleAs: "json" + }).then(function(data) + { + var mechMap = data.mechanisms; + + if (containsMechanism(mechMap, "CRAM-MD5")) + { + saslCramMD5(dojo.byId("username").value, dojo.byId("pass").value); + updateAuthentication(); + } + else if (containsMechanism(mechMap, "PLAIN")) + { + saslPlain(dojo.byId("username").value, dojo.byId("pass").value); + updateAuthentication(); + } + else + { + alert("No supported SASL mechanism offered: " + mechMap); + } + } + ); + + }; @@ -170,13 +205,13 @@ var updateAuthentication = function updateAuthentication() if(data.user) { dojo.byId("authenticatedUser").innerHTML = data.user; - dojo.style(button.domNode, {visibility: 'hidden'}); - dojo.style(usernameSpan, {visibility: 'visible'}); + dojo.style(button.domNode, {display: 'none'}); + dojo.style(usernameSpan, {display: 'block'}); } else { - dojo.style(button.domNode, {visibility: 'visible'}); - dojo.style(usernameSpan, {visibility: 'hidden'}); + dojo.style(button.domNode, {display: 'block'}); + dojo.style(usernameSpan, {display: 'none'}); } } ); @@ -198,13 +233,13 @@ require(["dijit/form/DropDownButton", "dijit/TooltipDialog", "dijit/form/TextBox dropDown: dialog }); - usernameSpan = domConstruct.create("span", { innerHTML: 'User: ', - style: { visibility: "hidden" }}); + usernameSpan = domConstruct.create("span", { innerHTML: 'User: [logout]', + style: { display: "none" }}); var loginDiv = dom.byId("login"); - loginDiv.appendChild(button.domNode); loginDiv.appendChild(usernameSpan); + loginDiv.appendChild(button.domNode); diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js index 08fdf5c99b..5557c37a2c 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js @@ -58,10 +58,10 @@ define(["dojo/_base/xhr"], return exchangeName == null || exchangeName == "" || "<>" == exchangeName || exchangeName.indexOf("amq.") == 0 || exchangeName.indexOf("qpid.") == 0; }; - util.deleteGridSelections = function(updater, gridName, url, confirmationMessageStart) + util.deleteGridSelections = function(updater, grid, url, confirmationMessageStart) { - var grid = updater[gridName].grid; var data = grid.selection.getSelected(); + if(data.length) { var confirmationMessage = null; @@ -103,7 +103,8 @@ define(["dojo/_base/xhr"], xhr.del({url: query, sync: true, handleAs: "json"}).then( function(data) { - grid.setQuery({id: "*"}); + // TODO why query *?? + //grid.setQuery({id: "*"}); grid.selection.deselectAll(); updater.update(); }, diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js index 37bae1ef8e..5a5a6515ef 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Exchange.js @@ -115,7 +115,7 @@ define(["dojo/_base/xhr", { util.deleteGridSelections( this.exchangeUpdater, - "bindingsGrid", + that.exchangeUpdater.bindingsGrid.grid, "rest/binding/"+ encodeURIComponent(this.getVirtualHostName()) + "/" + encodeURIComponent(this.name), "Are you sure you want to delete binding for queue"); } diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js new file mode 100644 index 0000000000..4e05f4b0ea --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/GroupProvider.js @@ -0,0 +1,109 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/query", + "dojo/_base/connect", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/util", + "qpid/common/UpdatableStore", + "dojox/grid/EnhancedGrid", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojo/domReady!"], + function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid) { + + function GroupProvider(name, parent, controller) { + this.name = name; + this.controller = controller; + this.modelObj = { type: "groupprovider", name: name }; + if(parent) { + this.modelObj.parent = {}; + this.modelObj.parent[ parent.type] = parent; + } + } + + GroupProvider.prototype.getTitle = function() { + return "GroupProvider"; + }; + + GroupProvider.prototype.open = function(contentPane) { + var that = this; + this.contentPane = contentPane; + xhr.get({url: "showGroupProvider.html", + sync: true, + load: function(data) { + contentPane.containerNode.innerHTML = data; + parser.parse(contentPane.containerNode); + + that.groupProviderAdapter = new GroupProviderUpdater(contentPane.containerNode, that.modelObj, that.controller); + + updater.add( that.groupProviderAdapter ); + + that.groupProviderAdapter.update(); + + }}); + }; + + GroupProvider.prototype.close = function() { + updater.remove( this.groupProviderAdapter ); + }; + + function GroupProviderUpdater(node, groupProviderObj, controller) + { + this.controller = controller; + this.name = query(".name", node)[0]; + this.query = "rest/groupprovider/"+encodeURIComponent(groupProviderObj.name); + + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) + { + that.groupProviderData = data[0]; + + util.flattenStatistics( that.groupProviderData ); + + that.updateHeader(); + + require(["qpid/management/groupprovider/"+that.groupProviderData.type], + function(SpecificProvider) { + that.details = new SpecificProvider(node, groupProviderObj, controller); + that.details.update(); + }); + + }); + + } + + GroupProviderUpdater.prototype.updateHeader = function() + { + this.name.innerHTML = this.groupProviderData[ "name" ]; + }; + + GroupProviderUpdater.prototype.update = function() + { + var that = this; + }; + + return GroupProvider; + }); diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js index 957f2381cf..2efc46476d 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/VirtualHost.js @@ -72,7 +72,7 @@ define(["dojo/_base/xhr", function(evt){ util.deleteGridSelections( that.vhostUpdater, - "queuesGrid", + that.vhostUpdater.queuesGrid.grid, "rest/queue/"+ encodeURIComponent(that.name), "Are you sure you want to delete queue"); } @@ -87,7 +87,7 @@ define(["dojo/_base/xhr", { util.deleteGridSelections( that.vhostUpdater, - "exchangesGrid", + that.vhostUpdater.exchangesGrid.grid, "rest/exchange/"+ encodeURIComponent(that.name), "Are you sure you want to delete exchange"); } diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js index 1aa05a5a3c..5d3a666760 100644 --- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js @@ -27,13 +27,17 @@ define(["dojo/dom", "qpid/management/Queue", "qpid/management/Connection", "qpid/management/AuthenticationProvider", + "qpid/management/GroupProvider", + "qpid/management/group/Group", "dojo/ready", "dojo/domReady!"], - function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, ready) { + function (dom, registry, ContentPane, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, GroupProvider, Group, ready) { var controller = {}; var constructors = { broker: Broker, virtualhost: VirtualHost, exchange: Exchange, - queue: Queue, connection: Connection, authenticationprovider: AuthProvider }; + queue: Queue, connection: Connection, + authenticationprovider: AuthProvider, groupprovider: GroupProvider, + group: Group }; var tabDiv = dom.byId("managedViews"); diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js new file mode 100644 index 0000000000..ea918644e9 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/Group.js @@ -0,0 +1,204 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/query", + "dijit/registry", + "dojo/_base/connect", + "dojo/_base/event", + "dojo/json", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/util", + "qpid/common/formatter", + "qpid/common/UpdatableStore", + "dojo/store/JsonRest", + "dojox/grid/EnhancedGrid", + "dojo/data/ObjectStore", + "qpid/management/group/addGroupMember", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojo/domReady!"], + function (xhr, parser, query, registry, connect, event, json, properties, updater, util, formatter, + UpdatableStore, JsonRest, EnhancedGrid, ObjectStore, addGroupMember) { + + function Group(name, parent, controller) { + this.name = name; + this.controller = controller; + this.modelObj = { type: "group", name: name }; + + if(parent) { + this.modelObj.parent = {}; + this.modelObj.parent[ parent.type] = parent; + } + } + + Group.prototype.getGroupName = function() + { + return this.name; + }; + + + Group.prototype.getGroupProviderName = function() + { + return this.modelObj.parent.groupprovider.name; + }; + + Group.prototype.getTitle = function() + { + return "Group: " + this.name; + }; + + Group.prototype.open = function(contentPane) { + var that = this; + this.contentPane = contentPane; + + xhr.get({url: "group/showGroup.html", + sync: true, + load: function(data) { + contentPane.containerNode.innerHTML = data; + parser.parse(contentPane.containerNode); + + that.groupUpdater = new GroupUpdater(contentPane.containerNode, that, that.controller); + + updater.add( that.groupUpdater ); + + that.groupUpdater.update(); + + var addGroupMemberButton = query(".addGroupMemberButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(addGroupMemberButton), "onClick", + function(evt){ + addGroupMember.show(that.getGroupProviderName(), that.getGroupName()) + } + ); + + var removeGroupMemberButton = query(".removeGroupMemberButton", contentPane.containerNode)[0]; + connect.connect(registry.byNode(removeGroupMemberButton), "onClick", + function(evt){ + util.deleteGridSelections( + that.groupUpdater, + that.groupUpdater.groupMembersUpdatableStore.grid, + "rest/groupmember/"+ encodeURIComponent(that.getGroupProviderName()) + + "/" + encodeURIComponent(that.getGroupName()), + "Are you sure you want to remove group member"); + } + ); + }}); + }; + + Group.prototype.close = function() { + updater.remove( this.groupUpdater ); + }; + + function GroupUpdater(containerNode, groupObj, controller) + { + var that = this; + + function findNode(name) { + return query("." + name, containerNode)[0]; + } + + function storeNodes(names) + { + for(var i = 0; i < names.length; i++) { + that[names[i]] = findNode(names[i]); + } + } + + storeNodes(["name", + "state", + "durable", + "lifetimePolicy", + "type"]); + + this.query = "rest/groupmember/"+ encodeURIComponent(groupObj.getGroupProviderName()) + "/" + encodeURIComponent(groupObj.getGroupName()); + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data) + { + that.groupMemberData = data; + + util.flattenStatistics( that.groupMemberData ); + + var gridProperties = { + keepSelection: true, + plugins: { + pagination: { + pageSizes: ["10", "25", "50", "100"], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: true + + }}; + + that.groupMembersUpdatableStore = new UpdatableStore(that.groupMemberData, findNode("groupMembers"), + [ { name: "Group Member Name", field: "name", width: "100%" }], + function(obj) + { + connect.connect(obj.grid, "onRowDblClick", obj.grid, + function(evt){ + + }); + } , gridProperties, EnhancedGrid); + + }); + + } + + GroupUpdater.prototype.update = function() + { + + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + that.groupMemberData = data; + + util.flattenStatistics( that.groupMemberData ); + + that.groupMembersUpdatableStore.update(that.groupMemberData); + }); + }; + + Group.prototype.deleteGroupMember = function() { + if(confirm("Are you sure you want to delete group member'" +this.name+"'?")) { + var query = "rest/groupmember/"+ encodeURIComponent(this.getGroupProviderName()) + "/" + encodeURIComponent(this.name); + this.success = true + var that = this; + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) { + that.contentPane.onClose() + that.controller.tabContainer.removeChild(that.contentPane); + that.contentPane.destroyRecursive(); + }, + function(error) {that.success = false; that.failureReason = error;}); + if(!this.success ) { + alert("Error:" + this.failureReason); + } + } + } + + return Group; + }); diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js new file mode 100644 index 0000000000..1861cc6ffe --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/group/addGroupMember.js @@ -0,0 +1,108 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define(["dojo/_base/xhr", + "dojo/dom", + "dojo/dom-construct", + "dojo/_base/window", + "dijit/registry", + "dojo/parser", + "dojo/_base/array", + "dojo/_base/event", + 'dojo/_base/json', + "dijit/form/NumberSpinner", // required by the form + /* dojox/ validate resources */ + "dojox/validate/us", "dojox/validate/web", + /* basic dijit classes */ + "dijit/Dialog", + "dijit/form/CheckBox", "dijit/form/Textarea", + "dijit/form/FilteringSelect", "dijit/form/TextBox", + "dijit/form/ValidationTextBox", "dijit/form/DateTextBox", + "dijit/form/TimeTextBox", "dijit/form/Button", + "dijit/form/RadioButton", "dijit/form/Form", + "dijit/form/DateTextBox", + /* basic dojox classes */ + "dojox/form/BusyButton", "dojox/form/CheckedMultiSelect", + "dojo/domReady!"], + function (xhr, dom, construct, win, registry, parser, array, event, json) { + + var addGroupMember = {}; + + var node = construct.create("div", null, win.body(), "last"); + + var convertToGroupMember = function convertToGroupMember(formValues) + { + var newGroupMember = {}; + newGroupMember.name = formValues.name; + return newGroupMember; + }; + + xhr.get({url: "group/addGroupMember.html", + sync: true, + load: function(data) { + var theForm; + node.innerHTML = data; + addGroupMember.dialogNode = dom.byId("addGroupMember"); + parser.instantiate([addGroupMember.dialogNode]); + + theForm = registry.byId("formAddGroupMember"); + theForm.on("submit", function(e) { + + event.stop(e); + if(theForm.validate()){ + + var newGroupMember = convertToGroupMember(theForm.getValues()); + var that = this; + xhr.put({url: "rest/groupmember/"+encodeURIComponent(addGroupMember.groupProvider) + + "/" + encodeURIComponent(addGroupMember.group) + "/" + encodeURIComponent(newGroupMember.name), sync: true, handleAs: "json", + headers: { "Content-Type": "application/json"}, + putData: json.toJson(newGroupMember), + load: function(x) {that.success = true; }, + error: function(error) {that.success = false; that.failureReason = error;}}); + + if(this.success === true) + { + registry.byId("addGroupMember").hide(); + } + else + { + alert("Error:" + this.failureReason); + } + + return false; + + + }else{ + alert('Form contains invalid data. Please correct first'); + return false; + } + + }); + }}); + + addGroupMember.show = function(groupProvider, group) { + addGroupMember.groupProvider = groupProvider; + addGroupMember.group = group; + registry.byId("formAddGroupMember").reset(); + registry.byId("addGroupMember").show(); + }; + + return addGroupMember; + }); \ No newline at end of file diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js new file mode 100644 index 0000000000..44fc9702e2 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/FileGroupManager.js @@ -0,0 +1,251 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define(["dojo/_base/xhr", + "dojo/dom", + "dojo/parser", + "dojo/query", + "dojo/dom-construct", + "dojo/_base/connect", + "dojo/_base/window", + "dojo/_base/event", + "dojo/_base/json", + "dijit/registry", + "qpid/common/util", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/UpdatableStore", + "dojox/grid/EnhancedGrid", + "dojox/grid/enhanced/plugins/Pagination", + "dojox/grid/enhanced/plugins/IndirectSelection", + "dojox/validate/us", "dojox/validate/web", + "dijit/Dialog", + "dijit/form/TextBox", + "dijit/form/ValidationTextBox", + "dijit/form/TimeTextBox", "dijit/form/Button", + "dijit/form/Form", + "dijit/form/DateTextBox", + "dojo/domReady!"], + function (xhr, dom, parser, query, construct, connect, win, event, json, registry, util, properties, updater, UpdatableStore, EnhancedGrid) { + function DatabaseGroupManager(containerNode, groupProviderObj, controller) { + var node = construct.create("div", null, containerNode, "last"); + var that = this; + this.name = groupProviderObj.name; + xhr.get({url: "groupprovider/showFileGroupManager.html", + sync: true, + load: function(data) { + node.innerHTML = data; + parser.parse(node); + + + that.groupDatabaseUpdater= new GroupProviderUpdater(node, groupProviderObj, controller); + + updater.add( that.groupDatabaseUpdater); + + that.groupDatabaseUpdater.update(); + + + }}); + } + + DatabaseGroupManager.prototype.update = function() { + this.groupDatabaseUpdater.update(); + }; + + DatabaseGroupManager.prototype.close = function() { + updater.remove( this.groupDatabaseUpdater ); + }; + + function GroupProviderUpdater(node, groupProviderObj, controller) + { + this.controller = controller; + this.query = "rest/groupprovider/"+encodeURIComponent(groupProviderObj.name); + this.name = groupProviderObj.name; + var that = this; + + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + that.groupProviderData = data[0]; + + util.flattenStatistics( that.groupProviderData ); + + var groupDiv = query(".groups")[0]; + + var gridProperties = { + height: 400, + keepSelection: true, + plugins: { + pagination: { + pageSizes: ["10", "25", "50", "100"], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: true + + }}; + + + that.groupsGrid = + new UpdatableStore(that.groupProviderData.groups, groupDiv, + [ { name: "Group Name", field: "name", width: "100%" } + ], null, gridProperties, EnhancedGrid); + + + var addGroupButton = query(".addGroupButton", node)[0]; + connect.connect(registry.byNode(addGroupButton), "onClick", function(evt){ addGroup.show(groupProviderObj.name) }); + + var deleteMessagesButton = query(".deleteGroupButton", node)[0]; + var deleteWidget = registry.byNode(deleteMessagesButton); + connect.connect(deleteWidget, "onClick", + function(evt){ + event.stop(evt); + that.deleteGroups(); + }); + }); + } + + GroupProviderUpdater.prototype.deleteGroups = function() + { + var grid = this.groupsGrid.grid; + var data = grid.selection.getSelected(); + if(data.length) { + var that = this; + if(confirm("Delete " + data.length + " groups?")) { + var i, queryParam; + for(i = 0; i - - - - - Qpid Management - - - - - - - - - - - - - - -
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
- - - \ No newline at end of file diff --git a/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html b/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html new file mode 100644 index 0000000000..914857db5c --- /dev/null +++ b/java/broker-plugins/management-http/src/main/java/resources/showGroupProvider.html @@ -0,0 +1,25 @@ + +
+ Name: +
+ Type: +
\ No newline at end of file diff --git a/java/broker-plugins/management-http/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PluginFactory b/java/broker-plugins/management-http/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PluginFactory new file mode 100644 index 0000000000..7ffb9a9013 --- /dev/null +++ b/java/broker-plugins/management-http/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PluginFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.management.plugin.HttpManagementFactory diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementFactoryTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementFactoryTest.java new file mode 100644 index 0000000000..bb4c46826c --- /dev/null +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementFactoryTest.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.management.plugin; + +import static org.mockito.Mockito.mock; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.plugin.PluginFactory; +import org.apache.qpid.test.utils.QpidTestCase; + +public class HttpManagementFactoryTest extends QpidTestCase +{ + private static final int SESSION_TIMEOUT = 3600; + + private PluginFactory _pluginFactory = new HttpManagementFactory(); + private Map _attributes = new HashMap(); + private Broker _broker = mock(Broker.class); + private UUID _id = UUID.randomUUID(); + + public void testCreateInstanceReturnsNullWhenPluginTypeMissing() throws Exception + { + assertNull(_pluginFactory.createInstance(_id, _attributes, _broker)); + } + public void testCreateInstanceReturnsNullWhenPluginTypeNotHttp() + { + _attributes.put(PluginFactory.PLUGIN_TYPE, "notHttp"); + assertNull(_pluginFactory.createInstance(_id, _attributes, _broker)); + } + + public void testCreateInstance() throws Exception + { + _attributes.put(PluginFactory.PLUGIN_TYPE, HttpManagement.PLUGIN_TYPE); + _attributes.put(HttpManagement.TIME_OUT, SESSION_TIMEOUT); + + HttpManagement management = (HttpManagement) _pluginFactory.createInstance(_id, _attributes, _broker); + + assertEquals(_broker, management.getBroker()); + assertEquals(SESSION_TIMEOUT, management.getSessionTimeout()); + } + +} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/Asserts.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/Asserts.java deleted file mode 100644 index 2595007574..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/Asserts.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.management.plugin.servlet.rest; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; - -import javax.jms.JMSException; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.Connection; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; - -public class Asserts -{ - public static final String STATISTICS_ATTRIBUTE = "statistics"; - - public static void assertVirtualHost(String virtualHostName, Map virtualHost) - { - assertNotNull("Virtualhost " + virtualHostName + " data are not found", virtualHost); - assertAttributesPresent(virtualHost, VirtualHost.AVAILABLE_ATTRIBUTES, VirtualHost.TIME_TO_LIVE, - VirtualHost.CREATED, VirtualHost.UPDATED, VirtualHost.SUPPORTED_QUEUE_TYPES, VirtualHost.STORE_CONFIGURATION); - - assertEquals("Unexpected value of attribute " + VirtualHost.NAME, virtualHostName, virtualHost.get(VirtualHost.NAME)); - assertNotNull("Unexpected value of attribute " + VirtualHost.ID, virtualHost.get(VirtualHost.ID)); - assertEquals("Unexpected value of attribute " + VirtualHost.STATE, State.ACTIVE.name(), - virtualHost.get(VirtualHost.STATE)); - assertEquals("Unexpected value of attribute " + VirtualHost.DURABLE, Boolean.TRUE, - virtualHost.get(VirtualHost.DURABLE)); - assertEquals("Unexpected value of attribute " + VirtualHost.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), - virtualHost.get(VirtualHost.LIFETIME_POLICY)); - assertEquals("Unexpected value of attribute " + VirtualHost.DEAD_LETTER_QUEUE_ENABLED, Boolean.FALSE, - virtualHost.get(VirtualHost.DEAD_LETTER_QUEUE_ENABLED)); - - @SuppressWarnings("unchecked") - Collection exchangeTypes = (Collection) virtualHost.get(VirtualHost.SUPPORTED_EXCHANGE_TYPES); - assertEquals("Unexpected value of attribute " + VirtualHost.SUPPORTED_EXCHANGE_TYPES, - new HashSet(Arrays.asList("headers", "topic", "direct", "fanout", "management")), - new HashSet(exchangeTypes)); - - @SuppressWarnings("unchecked") - Map statistics = (Map) virtualHost.get(STATISTICS_ATTRIBUTE); - Asserts.assertAttributesPresent(statistics, VirtualHost.AVAILABLE_STATISTICS, VirtualHost.BYTES_RETAINED, - VirtualHost.LOCAL_TRANSACTION_BEGINS, VirtualHost.LOCAL_TRANSACTION_ROLLBACKS, - VirtualHost.MESSAGES_RETAINED, VirtualHost.STATE_CHANGED, VirtualHost.XA_TRANSACTION_BRANCH_ENDS, - VirtualHost.XA_TRANSACTION_BRANCH_STARTS, VirtualHost.XA_TRANSACTION_BRANCH_SUSPENDS); - - } - - public static void assertQueue(String queueName, String queueType, Map queueData) - { - assertQueue(queueName, queueType, queueData, null); - } - - public static void assertQueue(String queueName, String queueType, Map queueData, Map expectedAttributes) - { - assertNotNull("Queue " + queueName + " is not found!", queueData); - Asserts.assertAttributesPresent(queueData, Queue.AVAILABLE_ATTRIBUTES, Queue.CREATED, Queue.UPDATED, - Queue.DESCRIPTION, Queue.TIME_TO_LIVE, Queue.ALTERNATE_EXCHANGE, Queue.OWNER, Queue.NO_LOCAL, Queue.LVQ_KEY, - Queue.SORT_KEY, Queue.MESSAGE_GROUP_KEY, Queue.MESSAGE_GROUP_DEFAULT_GROUP, - Queue.MESSAGE_GROUP_SHARED_GROUPS, Queue.PRIORITIES); - - assertEquals("Unexpected value of queue attribute " + Queue.NAME, queueName, queueData.get(Queue.NAME)); - assertNotNull("Unexpected value of queue attribute " + Queue.ID, queueData.get(Queue.ID)); - assertEquals("Unexpected value of queue attribute " + Queue.STATE, State.ACTIVE.name(), queueData.get(Queue.STATE)); - assertEquals("Unexpected value of queue attribute " + Queue.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), - queueData.get(Queue.LIFETIME_POLICY)); - assertEquals("Unexpected value of queue attribute " + Queue.TYPE, queueType, queueData.get(Queue.TYPE)); - if (expectedAttributes == null) - { - assertEquals("Unexpected value of queue attribute " + Queue.EXCLUSIVE, Boolean.FALSE, queueData.get(Queue.EXCLUSIVE)); - assertEquals("Unexpected value of queue attribute " + Queue.MAXIMUM_DELIVERY_ATTEMPTS, 0, - queueData.get(Queue.MAXIMUM_DELIVERY_ATTEMPTS)); - assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 0, - queueData.get(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES)); - assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 0, - queueData.get(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES)); - assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_STOPPED, Boolean.FALSE, - queueData.get(Queue.QUEUE_FLOW_STOPPED)); - } - else - { - for (Map.Entry attribute : expectedAttributes.entrySet()) - { - assertEquals("Unexpected value of " + queueName + " queue attribute " + attribute.getKey(), - attribute.getValue(), queueData.get(attribute.getKey())); - } - } - - assertNotNull("Unexpected value of queue attribute statistics", queueData.get(Asserts.STATISTICS_ATTRIBUTE)); - @SuppressWarnings("unchecked") - Map statistics = (Map) queueData.get(Asserts.STATISTICS_ATTRIBUTE); - Asserts.assertAttributesPresent(statistics, Queue.AVAILABLE_STATISTICS, Queue.DISCARDS_TTL_BYTES, - Queue.DISCARDS_TTL_MESSAGES, Queue.STATE_CHANGED); - } - - public static void assertAttributesPresent(Map data, String[] attributes) - { - for (String name : attributes) - { - assertNotNull("Attribute " + name + " is not present", data.get(name)); - } - } - - public static void assertAttributesPresent(Map data, Collection attributes, - String... unsupportedAttributes) - { - for (String name : attributes) - { - boolean unsupported = false; - for (String unsupportedAttribute : unsupportedAttributes) - { - if (unsupportedAttribute.equals(name)) - { - unsupported = true; - break; - } - } - if (unsupported) - { - continue; - } - assertNotNull("Attribute " + name + " is not present", data.get(name)); - } - } - - public static void assertConnection(Map connectionData, AMQConnection connection) throws JMSException - { - assertNotNull("Unexpected connection data", connectionData); - assertAttributesPresent(connectionData, Connection.AVAILABLE_ATTRIBUTES, Connection.STATE, Connection.DURABLE, - Connection.LIFETIME_POLICY, Connection.TIME_TO_LIVE, Connection.CREATED, Connection.UPDATED, - Connection.INCOMING, Connection.REMOTE_PROCESS_NAME, Connection.REMOTE_PROCESS_PID, - Connection.LOCAL_ADDRESS, Connection.PROPERTIES); - - assertEquals("Unexpected value of connection attribute " + Connection.SESSION_COUNT_LIMIT, - (int) connection.getMaximumChannelCount(), connectionData.get(Connection.SESSION_COUNT_LIMIT)); - assertEquals("Unexpected value of connection attribute " + Connection.CLIENT_ID, "clientid", - connectionData.get(Connection.CLIENT_ID)); - assertEquals("Unexpected value of connection attribute " + Connection.PRINCIPAL, "guest", - connectionData.get(Connection.PRINCIPAL)); - - @SuppressWarnings("unchecked") - Map statistics = (Map) connectionData.get(STATISTICS_ATTRIBUTE); - assertAttributesPresent(statistics, Connection.AVAILABLE_STATISTICS, Connection.LOCAL_TRANSACTION_BEGINS, - Connection.LOCAL_TRANSACTION_ROLLBACKS, Connection.STATE_CHANGED, Connection.XA_TRANSACTION_BRANCH_ENDS, - Connection.XA_TRANSACTION_BRANCH_STARTS, Connection.XA_TRANSACTION_BRANCH_SUSPENDS); - assertEquals("Unexpected value of connection statistics attribute " + Connection.SESSION_COUNT, 1, - statistics.get(Connection.SESSION_COUNT)); - } - - public static void assertPortAttributes(Map port) - { - assertAttributesPresent(port, Port.AVAILABLE_ATTRIBUTES, Port.CREATED, Port.UPDATED); - - assertNotNull("Unexpected value of attribute " + Port.ID, port.get(Port.ID)); - assertEquals("Unexpected value of attribute " + Port.DURABLE, Boolean.FALSE, port.get(Port.DURABLE)); - assertEquals("Unexpected value of attribute " + Port.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), - port.get(Broker.LIFETIME_POLICY)); - assertEquals("Unexpected value of attribute " + Port.STATE, State.ACTIVE.name(), port.get(Port.STATE)); - assertEquals("Unexpected value of attribute " + Port.TIME_TO_LIVE, 0, port.get(Port.TIME_TO_LIVE)); - assertNotNull("Unexpected value of attribute " + Port.BINDING_ADDRESS, port.get(Port.BINDING_ADDRESS)); - assertNotNull("Unexpected value of attribute " + Port.PROTOCOLS, port.get(Port.PROTOCOLS)); - assertNotNull("Unexpected value of attribute " + Port.NAME, port.get(Port.NAME)); - - @SuppressWarnings("unchecked") - Collection transports = (Collection) port.get(Port.TRANSPORTS); - assertEquals("Unexpected value of attribute " + Port.TRANSPORTS, new HashSet(Arrays.asList("TCP")), - new HashSet(transports)); - } - - public static void assertDurableExchange(String exchangeName, String type, Map exchangeData) - { - assertExchange(exchangeName, type, exchangeData); - - assertEquals("Unexpected value of exchange attribute " + Exchange.DURABLE, Boolean.TRUE, - exchangeData.get(Exchange.DURABLE)); - } - - public static void assertExchange(String exchangeName, String type, Map exchangeData) - { - assertNotNull("Exchange " + exchangeName + " is not found!", exchangeData); - assertAttributesPresent(exchangeData, Exchange.AVAILABLE_ATTRIBUTES, Exchange.CREATED, Exchange.UPDATED, - Exchange.ALTERNATE_EXCHANGE, Exchange.TIME_TO_LIVE); - - assertEquals("Unexpected value of exchange attribute " + Exchange.NAME, exchangeName, - exchangeData.get(Exchange.NAME)); - assertNotNull("Unexpected value of exchange attribute " + Exchange.ID, exchangeData.get(VirtualHost.ID)); - assertEquals("Unexpected value of exchange attribute " + Exchange.STATE, State.ACTIVE.name(), - exchangeData.get(Exchange.STATE)); - - assertEquals("Unexpected value of exchange attribute " + Exchange.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), - exchangeData.get(Exchange.LIFETIME_POLICY)); - assertEquals("Unexpected value of exchange attribute " + Exchange.TYPE, type, exchangeData.get(Exchange.TYPE)); - assertNotNull("Unexpected value of exchange attribute statistics", exchangeData.get(STATISTICS_ATTRIBUTE)); - - @SuppressWarnings("unchecked") - Map statistics = (Map) exchangeData.get(STATISTICS_ATTRIBUTE); - assertAttributesPresent(statistics, Exchange.AVAILABLE_STATISTICS, Exchange.STATE_CHANGED, Exchange.PRODUCER_COUNT); - } - - public static void assertBinding(String bindingName, String queueName, String exchange, Map binding) - { - assertNotNull("Binding map should not be null", binding); - assertAttributesPresent(binding, Binding.AVAILABLE_ATTRIBUTES, Binding.STATE, Binding.TIME_TO_LIVE, - Binding.CREATED, Binding.UPDATED); - - assertEquals("Unexpected binding attribute " + Binding.NAME, bindingName, binding.get(Binding.NAME)); - assertEquals("Unexpected binding attribute " + Binding.QUEUE, queueName, binding.get(Binding.QUEUE)); - assertEquals("Unexpected binding attribute " + Binding.EXCHANGE, exchange, binding.get(Binding.EXCHANGE)); - assertEquals("Unexpected binding attribute " + Binding.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), - binding.get(Binding.LIFETIME_POLICY)); - } - - public static void assertBinding(String queueName, String exchange, Map binding) - { - assertBinding(queueName, queueName, exchange, binding); - } - -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java deleted file mode 100644 index 5e6d9a998a..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/AuthenticationProviderRestTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.management.plugin.servlet.rest; - -import java.util.List; -import java.util.Map; - -import org.apache.qpid.server.model.AuthenticationProvider; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.User; - -public class AuthenticationProviderRestTest extends QpidRestTestCase -{ - - public void testGet() throws Exception - { - List> providerDetails = getJsonAsList("/rest/authenticationprovider"); - assertNotNull("Providers details cannot be null", providerDetails); - assertEquals("Unexpected number of providers", 1, providerDetails.size()); - for (Map provider : providerDetails) - { - assertProvider("PrincipalDatabaseAuthenticationManager", provider); - Map data = getJsonAsSingletonList("/rest/authenticationprovider/" - + provider.get(AuthenticationProvider.NAME)); - assertNotNull("Cannot load data for " + provider.get(AuthenticationProvider.NAME), data); - assertProvider("PrincipalDatabaseAuthenticationManager", data); - } - } - - private void assertProvider(String type, Map provider) - { - Asserts.assertAttributesPresent(provider, AuthenticationProvider.AVAILABLE_ATTRIBUTES, - AuthenticationProvider.CREATED, AuthenticationProvider.UPDATED, AuthenticationProvider.DESCRIPTION, - AuthenticationProvider.TIME_TO_LIVE); - assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.STATE, State.ACTIVE.name(), - provider.get(AuthenticationProvider.STATE)); - assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.LIFETIME_POLICY, - LifetimePolicy.PERMANENT.name(), provider.get(AuthenticationProvider.LIFETIME_POLICY)); - assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.DURABLE, Boolean.TRUE, - provider.get(AuthenticationProvider.DURABLE)); - assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.TYPE, type, - provider.get(AuthenticationProvider.TYPE)); - - @SuppressWarnings("unchecked") - List> users = (List>) provider.get("users"); - assertNotNull("Users are not found", users); - assertTrue("Unexpected number of users", users.size() > 1); - for (Map user : users) - { - assertNotNull("Attribute " + User.ID, user.get(User.ID)); - assertNotNull("Attribute " + User.NAME, user.get(User.NAME)); - } - } -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java deleted file mode 100644 index 1ed0d97185..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BindingRestTest.java +++ /dev/null @@ -1,129 +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.management.plugin.servlet.rest; - -import java.net.HttpURLConnection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.qpid.server.model.Binding; - -public class BindingRestTest extends QpidRestTestCase -{ - - public void testGetAllBindings() throws Exception - { - List> bindings = getJsonAsList("/rest/binding"); - assertNotNull("Bindings cannot be null", bindings); - assertTrue("Unexpected number of bindings", bindings.size() >= EXPECTED_HOSTS.length * EXPECTED_QUEUES.length); - for (Map binding : bindings) - { - Asserts.assertBinding((String) binding.get(Binding.NAME), (String) binding.get(Binding.EXCHANGE), binding); - } - } - - public void testGetVirtualHostBindings() throws Exception - { - List> bindings = getJsonAsList("/rest/binding/test"); - assertNotNull("Bindings cannot be null", bindings); - assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length * 2, bindings.size()); - for (String queueName : EXPECTED_QUEUES) - { - Map searchAttributes = new HashMap(); - searchAttributes.put(Binding.NAME, queueName); - searchAttributes.put(Binding.EXCHANGE, "amq.direct"); - - Map binding = find(searchAttributes, bindings); - Asserts.assertBinding(queueName, "amq.direct", binding); - - searchAttributes.put(Binding.EXCHANGE, "<>"); - - binding = find(searchAttributes, bindings); - Asserts.assertBinding(queueName, "<>", binding); - } - } - - public void testGetVirtualHostExchangeBindings() throws Exception - { - List> bindings = getJsonAsList("/rest/binding/test/amq.direct"); - assertNotNull("Bindings cannot be null", bindings); - assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length, bindings.size()); - for (String queueName : EXPECTED_QUEUES) - { - Map binding = find(Binding.NAME, queueName, bindings); - Asserts.assertBinding(queueName, "amq.direct", binding); - } - } - - public void testGetVirtualHostExchangeQueueBindings() throws Exception - { - List> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue"); - assertNotNull("Bindings cannot be null", bindings); - assertEquals("Unexpected number of bindings", 1, bindings.size()); - Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); - } - - - public void testDeleteBinding() throws Exception - { - List> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); - assertEquals("Unexpected number of bindings", 1, bindings.size()); - Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); - - HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/queue", "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - - bindings = getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); - assertEquals("Binding should be deleted", 0, bindings.size()); - } - - public void testDeleteBindingById() throws Exception - { - Map binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue"); - HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List> bindings = getJsonAsList("/rest/binding/test/amq.direct/queue"); - assertEquals("Binding should be deleted", 0, bindings.size()); - } - - public void testCreateBinding() throws Exception - { - String bindingName = getTestName(); - Map bindingData = new HashMap(); - bindingData.put(Binding.NAME, bindingName); - bindingData.put(Binding.QUEUE, "queue"); - bindingData.put(Binding.EXCHANGE, "amq.direct"); - - HttpURLConnection connection = openManagementConection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT"); - connection.connect(); - writeJsonRequest(connection, bindingData); - int responseCode = connection.getResponseCode(); - connection.disconnect(); - assertEquals("Unexpected response code", 201, responseCode); - Map binding = getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName); - - Asserts.assertBinding(bindingName, "queue", "amq.direct", binding); - } - -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java deleted file mode 100644 index 4bbe9155cd..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestHttpsTest.java +++ /dev/null @@ -1,86 +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.management.plugin.servlet.rest; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Map; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.model.Broker; - -public class BrokerRestHttpsTest extends QpidRestTestCase -{ - private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks"; - private static final String TRUSTSTORE_PASSWORD = "password"; - - @Override - public void setUp() throws Exception - { - setSystemProperty("javax.net.debug", "ssl"); - super.setUp(); - setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); - setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); - } - - @Override - protected void customizeConfiguration() throws ConfigurationException, IOException - { - setConfigurationProperty("management.enabled", "true"); - setConfigurationProperty("management.http.enabled", "false"); - setConfigurationProperty("management.https.enabled", "true"); - setConfigurationProperty("management.https.port", Integer.toString(getHttpPort())); - } - - @Override - protected String getHostName() - { - return "localhost"; - } - - @Override - protected String getProtocol() - { - return "https"; - } - - @Override - protected HttpURLConnection openManagementConection(String path) throws IOException - { - URL url = getManagementURL(path); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - ((HttpsURLConnection) httpCon).setSSLSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault()); - httpCon.setDoOutput(true); - return httpCon; - } - - public void testGetWithHttps() throws Exception - { - Map brokerDetails = getJsonAsSingletonList("/rest/broker"); - - Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED, - Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED); - } -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java deleted file mode 100644 index f2970e2ba9..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/BrokerRestTest.java +++ /dev/null @@ -1,118 +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.management.plugin.servlet.rest; - -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; - -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; - -public class BrokerRestTest extends QpidRestTestCase -{ - - private static final String BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE = "authenticationproviders"; - private static final String BROKER_PORTS_ATTRIBUTE = "ports"; - private static final String BROKER_VIRTUALHOSTS_ATTRIBUTE = "virtualhosts"; - private static final String BROKER_STATISTICS_ATTRIBUTE = "statistics"; - - public void testGet() throws Exception - { - Map brokerDetails = getJsonAsSingletonList("/rest/broker"); - - assertBrokerAttributes(brokerDetails); - - @SuppressWarnings("unchecked") - Map statistics = (Map) brokerDetails.get(BROKER_STATISTICS_ATTRIBUTE); - Asserts.assertAttributesPresent(statistics, new String[]{ "bytesIn", "messagesOut", "bytesOut", "messagesIn" }); - - @SuppressWarnings("unchecked") - List> virtualhosts = (List>) brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE); - assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size()); - - Asserts.assertVirtualHost("development", find(VirtualHost.NAME, "development", virtualhosts)); - Asserts.assertVirtualHost("localhost", find(VirtualHost.NAME, "localhost", virtualhosts)); - Asserts.assertVirtualHost("test", find(VirtualHost.NAME, "test", virtualhosts)); - - @SuppressWarnings("unchecked") - List> ports = (List>) brokerDetails.get(BROKER_PORTS_ATTRIBUTE); - assertEquals("Unexpected number of ports", 2, ports.size()); - - for (Map port : ports) - { - Asserts.assertPortAttributes(port); - } - - String bindingAddress = (String)ports.get(0).get(Port.BINDING_ADDRESS); - - Map amqpPort = find(Port.NAME, bindingAddress + ":" + getPort(), ports); - Map httpPort = find(Port.NAME, bindingAddress + ":" + getHttpPort(), ports); - - assertNotNull("Cannot find AMQP port", amqpPort); - assertNotNull("Cannot find HTTP port", httpPort); - - @SuppressWarnings("unchecked") - Collection port1Protocols = (Collection) amqpPort.get(Port.PROTOCOLS); - assertFalse("AMQP protocol list cannot contain HTTP", port1Protocols.contains("HTTP")); - - @SuppressWarnings("unchecked") - Collection port2Protocols = (Collection) httpPort.get(Port.PROTOCOLS); - assertEquals("Unexpected value of attribute " + Port.PROTOCOLS, new HashSet(Arrays.asList("HTTP")), - new HashSet(port2Protocols)); - } - - protected void assertBrokerAttributes(Map brokerDetails) - { - Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, - Broker.BYTES_RETAINED, Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, - Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED); - - assertEquals("Unexpected value of attribute " + Broker.BUILD_VERSION, QpidProperties.getBuildVersion(), - brokerDetails.get(Broker.BUILD_VERSION)); - assertEquals("Unexpected value of attribute " + Broker.OPERATING_SYSTEM, System.getProperty("os.name") + " " - + System.getProperty("os.version") + " " + System.getProperty("os.arch"), - brokerDetails.get(Broker.OPERATING_SYSTEM)); - assertEquals( - "Unexpected value of attribute " + Broker.PLATFORM, - System.getProperty("java.vendor") + " " - + System.getProperty("java.runtime.version", System.getProperty("java.version")), - brokerDetails.get(Broker.PLATFORM)); - assertEquals("Unexpected value of attribute " + Broker.DURABLE, Boolean.TRUE, brokerDetails.get(Broker.DURABLE)); - assertEquals("Unexpected value of attribute " + Broker.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), - brokerDetails.get(Broker.LIFETIME_POLICY)); - assertEquals("Unexpected value of attribute " + Broker.NAME, "Broker", brokerDetails.get(Broker.NAME)); - assertEquals("Unexpected value of attribute " + Broker.STATE, State.ACTIVE.name(), brokerDetails.get(Broker.STATE)); - - assertNotNull("Unexpected value of attribute " + Broker.ID, brokerDetails.get(Broker.ID)); - assertNotNull("Unexpected value of attribute statistics", brokerDetails.get(BROKER_STATISTICS_ATTRIBUTE)); - assertNotNull("Unexpected value of attribute virtualhosts", brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE)); - assertNotNull("Unexpected value of attribute ports", brokerDetails.get(BROKER_PORTS_ATTRIBUTE)); - assertNotNull("Unexpected value of attribute authenticationproviders", brokerDetails.get(BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE)); - } - -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java deleted file mode 100644 index 3661b94a7c..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConnectionRestTest.java +++ /dev/null @@ -1,213 +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.management.plugin.servlet.rest; - -import java.io.IOException; -import java.net.URLDecoder; -import java.util.List; -import java.util.Map; - -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.server.model.Connection; -import org.apache.qpid.server.model.Session; - -public class ConnectionRestTest extends QpidRestTestCase -{ - /** - * Message number to publish into queue - */ - private static final int MESSAGE_NUMBER = 5; - private static final int MESSAGE_SIZE = 6; - - private static final String SESSIONS_ATTRIBUTE = "sessions"; - - private javax.jms.Connection _connection; - private javax.jms.Session _session; - - public void setUp() throws Exception - { - super.setUp(); - - _connection = getConnection(); - _session = _connection.createSession(true, javax.jms.Session.SESSION_TRANSACTED); - String queueName = getTestQueueName(); - Destination queue = _session.createQueue(queueName); - MessageConsumer consumer = _session.createConsumer(queue); - MessageProducer producer = _session.createProducer(queue); - _connection.start(); - - // send messages - for (int i = 0; i < MESSAGE_NUMBER; i++) - { - producer.send(_session.createTextMessage("Test-" + i)); - } - _session.commit(); - - Message m = consumer.receive(1000l); - assertNotNull("Message was not received", m); - _session.commit(); - - // receive the rest of messages for rollback - for (int i = 0; i < MESSAGE_NUMBER - 1; i++) - { - m = consumer.receive(1000l); - assertNotNull("Message was not received", m); - } - _session.rollback(); - - // receive them again - for (int i = 0; i < MESSAGE_NUMBER - 1; i++) - { - m = consumer.receive(1000l); - assertNotNull("Message was not received", m); - } - } - - public void testGetAllConnections() throws Exception - { - List> connections = getJsonAsList("/rest/connection"); - assertEquals("Unexpected number of connections", 1, connections.size()); - Asserts.assertConnection(connections.get(0), (AMQConnection) _connection); - } - - public void testGetVirtualHostConnections() throws Exception - { - List> connections = getJsonAsList("/rest/connection/test"); - assertEquals("Unexpected number of connections", 1, connections.size()); - Asserts.assertConnection(connections.get(0), (AMQConnection) _connection); - } - - public void testGetConnectionByName() throws Exception - { - // get connection name - String connectionName = getConnectionName(); - - Map connectionDetails = getJsonAsSingletonList("/rest/connection/test/" - + URLDecoder.decode(connectionName, "UTF-8")); - assertConnection(connectionDetails); - } - - public void testGetAllSessions() throws Exception - { - List> sessions = getJsonAsList("/rest/session"); - assertEquals("Unexpected number of sessions", 1, sessions.size()); - assertSession(sessions.get(0), (AMQSession) _session); - } - - public void testGetVirtualHostSessions() throws Exception - { - List> sessions = getJsonAsList("/rest/session/test"); - assertEquals("Unexpected number of sessions", 1, sessions.size()); - assertSession(sessions.get(0), (AMQSession) _session); - } - - public void testGetConnectionSessions() throws Exception - { - // get connection name - String connectionName = getConnectionName(); - - List> sessions = getJsonAsList("/rest/session/test/" - + URLDecoder.decode(connectionName, "UTF-8")); - assertEquals("Unexpected number of sessions", 1, sessions.size()); - assertSession(sessions.get(0), (AMQSession) _session); - } - - public void testGetSessionByName() throws Exception - { - // get connection name - String connectionName = getConnectionName(); - - List> sessions = getJsonAsList("/rest/session/test/" - + URLDecoder.decode(connectionName, "UTF-8") + "/" + ((AMQSession) _session).getChannelId()); - assertEquals("Unexpected number of sessions", 1, sessions.size()); - assertSession(sessions.get(0), (AMQSession) _session); - } - - private void assertConnection(Map connectionDetails) throws JMSException - { - Asserts.assertConnection(connectionDetails, (AMQConnection) _connection); - - @SuppressWarnings("unchecked") - Map statistics = (Map) connectionDetails.get(Asserts.STATISTICS_ATTRIBUTE); - assertEquals("Unexpected value of connection statistics attribute " + Connection.BYTES_IN, MESSAGE_NUMBER - * MESSAGE_SIZE, statistics.get(Connection.BYTES_IN)); - assertEquals("Unexpected value of connection statistics attribute " + Connection.BYTES_OUT, MESSAGE_SIZE - + ((MESSAGE_NUMBER - 1) * MESSAGE_SIZE) * 2, statistics.get(Connection.BYTES_OUT)); - assertEquals("Unexpected value of connection statistics attribute " + Connection.MESSAGES_IN, MESSAGE_NUMBER, - statistics.get(Connection.MESSAGES_IN)); - assertEquals("Unexpected value of connection statistics attribute " + Connection.MESSAGES_OUT, - MESSAGE_NUMBER * 2 - 1, statistics.get(Connection.MESSAGES_OUT)); - - @SuppressWarnings("unchecked") - List> sessions = (List>) connectionDetails.get(SESSIONS_ATTRIBUTE); - assertNotNull("Sessions cannot be found", sessions); - assertEquals("Unexpected number of sessions", 1, sessions.size()); - assertSession(sessions.get(0), (AMQSession) _session); - } - - private void assertSession(Map sessionData, AMQSession session) - { - assertNotNull("Session map cannot be null", sessionData); - Asserts.assertAttributesPresent(sessionData, Session.AVAILABLE_ATTRIBUTES, Session.STATE, Session.DURABLE, - Session.LIFETIME_POLICY, Session.TIME_TO_LIVE, Session.CREATED, Session.UPDATED); - assertEquals("Unexpecte value of attribute " + Session.NAME, session.getChannelId() + "", - sessionData.get(Session.NAME)); - assertEquals("Unexpecte value of attribute " + Session.PRODUCER_FLOW_BLOCKED, Boolean.FALSE, - sessionData.get(Session.PRODUCER_FLOW_BLOCKED)); - assertEquals("Unexpecte value of attribute " + Session.CHANNEL_ID, session.getChannelId(), - sessionData.get(Session.CHANNEL_ID)); - - @SuppressWarnings("unchecked") - Map statistics = (Map) sessionData.get(Asserts.STATISTICS_ATTRIBUTE); - Asserts.assertAttributesPresent(statistics, Session.AVAILABLE_STATISTICS, Session.BYTES_IN, Session.BYTES_OUT, - Session.STATE_CHANGED, Session.UNACKNOWLEDGED_BYTES, Session.LOCAL_TRANSACTION_OPEN, - Session.XA_TRANSACTION_BRANCH_ENDS, Session.XA_TRANSACTION_BRANCH_STARTS, - Session.XA_TRANSACTION_BRANCH_SUSPENDS); - - assertEquals("Unexpecte value of statistic attribute " + Session.UNACKNOWLEDGED_MESSAGES, MESSAGE_NUMBER - 1, - statistics.get(Session.UNACKNOWLEDGED_MESSAGES)); - assertEquals("Unexpecte value of statistic attribute " + Session.LOCAL_TRANSACTION_BEGINS, 4, - statistics.get(Session.LOCAL_TRANSACTION_BEGINS)); - assertEquals("Unexpecte value of statistic attribute " + Session.LOCAL_TRANSACTION_ROLLBACKS, 1, - statistics.get(Session.LOCAL_TRANSACTION_ROLLBACKS)); - assertEquals("Unexpecte value of statistic attribute " + Session.CONSUMER_COUNT, 1, - statistics.get(Session.CONSUMER_COUNT)); - } - - private String getConnectionName() throws IOException - { - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - @SuppressWarnings("unchecked") - List> connections = (List>) hostDetails - .get(VirtualHostRestTest.VIRTUALHOST_CONNECTIONS_ATTRIBUTE); - assertEquals("Unexpected number of connections", 1, connections.size()); - Map connection = connections.get(0); - String connectionName = (String) connection.get(Connection.NAME); - return connectionName; - } -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java deleted file mode 100644 index 4904d2adf3..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ExchangeRestTest.java +++ /dev/null @@ -1,87 +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.management.plugin.servlet.rest; - -import java.net.URLDecoder; -import java.util.List; -import java.util.Map; - -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.Exchange; - -public class ExchangeRestTest extends QpidRestTestCase -{ - public void testGet() throws Exception - { - List> exchanges = getJsonAsList("/rest/exchange"); - assertNotNull("Exchanges cannot be null", exchanges); - assertTrue("Unexpected number of exchanges", exchanges.size() >= EXPECTED_HOSTS.length * EXPECTED_EXCHANGES.length); - for (Map exchange : exchanges) - { - Asserts.assertExchange((String) exchange.get(Exchange.NAME), (String) exchange.get(Exchange.TYPE), exchange); - } - } - - public void testGetHostExchanges() throws Exception - { - List> exchanges = getJsonAsList("/rest/exchange/test"); - assertNotNull("Users cannot be null", exchanges); - assertEquals("Unexpected number of exchanges", 6, EXPECTED_EXCHANGES.length); - for (String exchangeName : EXPECTED_EXCHANGES) - { - Map exchange = find(Exchange.NAME, exchangeName, exchanges); - assertExchange(exchangeName, exchange); - } - } - - public void testGetHostExchangeByName() throws Exception - { - for (String exchangeName : EXPECTED_EXCHANGES) - { - Map exchange = getJsonAsSingletonList("/rest/exchange/test/" - + URLDecoder.decode(exchangeName, "UTF-8")); - assertExchange(exchangeName, exchange); - } - } - - private void assertExchange(String exchangeName, Map exchange) - { - assertNotNull("Exchange with name " + exchangeName + " is not found", exchange); - String type = (String) exchange.get(Exchange.TYPE); - Asserts.assertExchange(exchangeName, type, exchange); - if ("direct".equals(type)) - { - assertBindings(exchange); - } - } - - private void assertBindings(Map exchange) - { - @SuppressWarnings("unchecked") - List> bindings = (List>) exchange.get("bindings"); - for (String queueName : EXPECTED_QUEUES) - { - Map binding = find(Binding.NAME, queueName, bindings); - Asserts.assertBinding(queueName, (String) exchange.get(Exchange.NAME), binding); - } - } - -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java deleted file mode 100644 index c64fd6e1da..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsRestTest.java +++ /dev/null @@ -1,42 +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.management.plugin.servlet.rest; - -import java.util.List; -import java.util.Map; - -public class LogRecordsRestTest extends QpidRestTestCase -{ - public void testGet() throws Exception - { - List> logs = getJsonAsList("/rest/logrecords"); - assertNotNull("Logs data cannot be null", logs); - assertTrue("Logs are not found", logs.size() > 0); - Map record = find("message", "[Broker] BRK-1004 : Qpid Broker Ready", logs); - - assertNotNull("BRK-1004 message is not found", record); - assertNotNull("Message id cannot be null", record.get("id")); - assertNotNull("Message timestamp cannot be null", record.get("timestamp")); - assertEquals("Unexpected log level", "INFO", record.get("level")); - assertEquals("Unexpected thread", "main", record.get("thread")); - assertEquals("Unexpected logger", "qpid.message.broker.ready", record.get("logger")); - } -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java deleted file mode 100644 index 492df43957..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/MessagesRestTest.java +++ /dev/null @@ -1,354 +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.management.plugin.servlet.rest; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import javax.jms.BytesMessage; -import javax.jms.Connection; -import javax.jms.DeliveryMode; -import javax.jms.Destination; -import javax.jms.Message; -import javax.jms.MessageProducer; -import javax.jms.Session; - -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.map.JsonMappingException; - -public class MessagesRestTest extends QpidRestTestCase -{ - - /** - * Message number to publish into queue - */ - private static final int MESSAGE_NUMBER = 12; - - private Connection _connection; - private Session _session; - private MessageProducer _producer; - private long _startTime; - private long _ttl; - - public void setUp() throws Exception - { - super.setUp(); - _startTime = System.currentTimeMillis(); - _connection = getConnection(); - _session = _connection.createSession(true, Session.SESSION_TRANSACTED); - String queueName = getTestQueueName(); - Destination queue = _session.createQueue(queueName); - _session.createConsumer(queue); - _producer = _session.createProducer(queue); - - _ttl = TimeUnit.DAYS.toMillis(1); - for (int i = 0; i < MESSAGE_NUMBER; i++) - { - Message m = _session.createTextMessage("Test-" + i); - m.setIntProperty("index", i); - if (i % 2 == 0) - { - _producer.send(m); - } - else - { - _producer.send(m, DeliveryMode.NON_PERSISTENT, 5, _ttl); - } - } - _session.commit(); - } - - public void testGet() throws Exception - { - String queueName = getTestQueueName(); - List> messages = getJsonAsList("/rest/message/test/" + queueName); - assertNotNull("Messages are not found", messages); - assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size()); - int position = 0; - for (Map message : messages) - { - assertMessage(position, message); - position++; - } - } - - public void testGetMessageContent() throws Exception - { - String queueName = getTestQueueName(); - - // add bytes message - BytesMessage byteMessage = _session.createBytesMessage(); - byte[] messageBytes = "Test".getBytes(); - byteMessage.writeBytes(messageBytes); - byteMessage.setStringProperty("test", "value"); - _producer.send(byteMessage); - _session.commit(); - - // get message IDs - List ids = getMesssageIds(queueName); - - Map message = getJsonAsMap("/rest/message/test/" + queueName + "/" + ids.get(0)); - assertMessageAttributes(message); - assertMessageAttributeValues(message, true); - - @SuppressWarnings("unchecked") - Map headers = (Map) message.get("headers"); - assertNotNull("Message headers are not found", headers); - assertEquals("Unexpected message header", 0, headers.get("index")); - - Long lastMessageId = ids.get(ids.size() - 1); - message = getJsonAsMap("/rest/message/test/" + queueName + "/" + lastMessageId); - assertMessageAttributes(message); - assertEquals("Unexpected message attribute mimeType", "application/octet-stream", message.get("mimeType")); - assertEquals("Unexpected message attribute size", 4, message.get("size")); - - @SuppressWarnings("unchecked") - Map bytesMessageHeader = (Map) message.get("headers"); - assertNotNull("Message headers are not found", bytesMessageHeader); - assertEquals("Unexpected message header", "value", bytesMessageHeader.get("test")); - - // get content - HttpURLConnection connection = openManagementConection("/rest/message-content/test/" + queueName + "/" - + lastMessageId, "GET"); - connection.connect(); - byte[] data = readConnectionInputStream(connection); - assertTrue("Unexpected message", Arrays.equals(messageBytes, data)); - - } - - public void testPostMoveMessages() throws Exception - { - String queueName = getTestQueueName(); - String queueName2 = queueName + "_2"; - Destination queue2 = _session.createQueue(queueName2); - _session.createConsumer(queue2); - - // get message IDs - List ids = getMesssageIds(queueName); - - // move half of the messages - int movedNumber = ids.size() / 2; - List movedMessageIds = new ArrayList(); - for (int i = 0; i < movedNumber; i++) - { - movedMessageIds.add(ids.remove(i)); - } - - // move messages - HttpURLConnection connection = openManagementConection("/rest/message/test/" + queueName, "POST"); - - Map messagesData = new HashMap(); - messagesData.put("messages", movedMessageIds); - messagesData.put("destinationQueue", queueName2); - messagesData.put("move", Boolean.TRUE); - - writeJsonRequest(connection, messagesData); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - - // check messages on target queue - List> messages = getJsonAsList("/rest/message/test/" + queueName2); - assertNotNull("Messages are not found", messages); - assertEquals("Unexpected number of messages", movedMessageIds.size(), messages.size()); - for (Long id : movedMessageIds) - { - Map message = find("id", id.intValue(), messages); - assertMessageAttributes(message); - } - - // check messages on original queue - messages = getJsonAsList("/rest/message/test/" + queueName); - assertNotNull("Messages are not found", messages); - assertEquals("Unexpected number of messages", ids.size(), messages.size()); - for (Long id : ids) - { - Map message = find("id", id.intValue(), messages); - assertMessageAttributes(message); - } - for (Long id : movedMessageIds) - { - Map message = find("id", id.intValue(), messages); - assertNull("Moved message " + id + " is found on original queue", message); - } - } - - public void testPostCopyMessages() throws Exception - { - String queueName = getTestQueueName(); - String queueName2 = queueName + "_2"; - Destination queue2 = _session.createQueue(queueName2); - _session.createConsumer(queue2); - - // get message IDs - List ids = getMesssageIds(queueName); - - // copy half of the messages - int copyNumber = ids.size() / 2; - List copyMessageIds = new ArrayList(); - for (int i = 0; i < copyNumber; i++) - { - copyMessageIds.add(ids.remove(i)); - } - - // copy messages - HttpURLConnection connection = openManagementConection("/rest/message/test/" + queueName, "POST"); - - Map messagesData = new HashMap(); - messagesData.put("messages", copyMessageIds); - messagesData.put("destinationQueue", queueName2); - - writeJsonRequest(connection, messagesData); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - - // check messages on target queue - List> messages = getJsonAsList("/rest/message/test/" + queueName2); - assertNotNull("Messages are not found", messages); - assertEquals("Unexpected number of messages", copyMessageIds.size(), messages.size()); - for (Long id : copyMessageIds) - { - Map message = find("id", id.intValue(), messages); - assertMessageAttributes(message); - } - - // check messages on original queue - messages = getJsonAsList("/rest/message/test/" + queueName); - assertNotNull("Messages are not found", messages); - assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size()); - for (Long id : ids) - { - Map message = find("id", id.intValue(), messages); - assertMessageAttributes(message); - } - for (Long id : copyMessageIds) - { - Map message = find("id", id.intValue(), messages); - assertMessageAttributes(message); - } - } - - public void testDeleteMessages() throws Exception - { - String queueName = getTestQueueName(); - - // get message IDs - List ids = getMesssageIds(queueName); - - // delete half of the messages - int deleteNumber = ids.size() / 2; - StringBuilder queryString = new StringBuilder(); - List deleteMessageIds = new ArrayList(); - for (int i = 0; i < deleteNumber; i++) - { - Long id = ids.remove(i); - deleteMessageIds.add(id); - if (queryString.length() > 0) - { - queryString.append("&"); - } - queryString.append("id=").append(id); - } - - // delete messages - HttpURLConnection connection = openManagementConection( - "/rest/message/test/" + queueName + "?" + queryString.toString(), "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - - // check messages on queue - List> messages = getJsonAsList("/rest/message/test/" + queueName); - assertNotNull("Messages are not found", messages); - assertEquals("Unexpected number of messages", ids.size(), messages.size()); - for (Long id : ids) - { - Map message = find("id", id.intValue(), messages); - assertMessageAttributes(message); - } - for (Long id : deleteMessageIds) - { - Map message = find("id", id.intValue(), messages); - assertNull("Message with id " + id + " was not deleted", message); - } - } - - private List getMesssageIds(String queueName) throws IOException, JsonParseException, JsonMappingException - { - List> messages = getJsonAsList("/rest/message/test/" + queueName); - List ids = new ArrayList(); - for (Map message : messages) - { - ids.add(((Number) message.get("id")).longValue()); - } - return ids; - } - - private void assertMessage(int position, Map message) - { - assertMessageAttributes(message); - - assertEquals("Unexpected message attribute position", position, message.get("position")); - assertEquals("Unexpected message attribute size", position < 10 ? 6 : 7, message.get("size")); - boolean even = position % 2 == 0; - assertMessageAttributeValues(message, even); - } - - private void assertMessageAttributeValues(Map message, boolean even) - { - if (even) - { - assertEquals("Unexpected message attribute expirationTime", 0, message.get("expirationTime")); - assertEquals("Unexpected message attribute priority", 4, message.get("priority")); - assertEquals("Unexpected message attribute persistent", Boolean.TRUE, message.get("persistent")); - } - else - { - assertEquals("Unexpected message attribute expirationTime", ((Number) message.get("timestamp")).longValue() - + _ttl, message.get("expirationTime")); - assertEquals("Unexpected message attribute priority", 5, message.get("priority")); - assertEquals("Unexpected message attribute persistent", Boolean.FALSE, message.get("persistent")); - } - assertEquals("Unexpected message attribute mimeType", "text/plain", message.get("mimeType")); - assertEquals("Unexpected message attribute userId", "guest", message.get("userId")); - assertEquals("Unexpected message attribute deliveryCount", 0, message.get("deliveryCount")); - assertEquals("Unexpected message attribute state", "Available", message.get("state")); - } - - private void assertMessageAttributes(Map message) - { - assertNotNull("Message map cannot be null", message); - assertNotNull("Unexpected message attribute deliveryCount", message.get("deliveryCount")); - assertNotNull("Unexpected message attribute state", message.get("state")); - assertNotNull("Unexpected message attribute id", message.get("id")); - assertNotNull("Message arrivalTime cannot be null", message.get("arrivalTime")); - assertNotNull("Message timestamp cannot be null", message.get("timestamp")); - assertTrue("Message arrivalTime cannot be null", ((Number) message.get("arrivalTime")).longValue() > _startTime); - assertNotNull("Message messageId cannot be null", message.get("messageId")); - assertNotNull("Unexpected message attribute mimeType", message.get("mimeType")); - assertNotNull("Unexpected message attribute userId", message.get("userId")); - assertNotNull("Message priority cannot be null", message.get("priority")); - assertNotNull("Message expirationTime cannot be null", message.get("expirationTime")); - assertNotNull("Message persistent cannot be null", message.get("persistent")); - } -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java deleted file mode 100644 index 739ef5c737..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/PortRestTest.java +++ /dev/null @@ -1,61 +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.management.plugin.servlet.rest; - -import java.net.URLDecoder; -import java.util.List; -import java.util.Map; - -import org.apache.qpid.server.model.Port; - -public class PortRestTest extends QpidRestTestCase -{ - public void testGet() throws Exception - { - List> ports = getJsonAsList("/rest/port/"); - assertNotNull("Port data cannot be null", ports); - assertEquals("Unexpected number of ports", 2, ports.size()); - int[] expectedPorts = { getPort(), getHttpPort() }; - for (int port : expectedPorts) - { - String portName = "0.0.0.0:" + port; - Map portData = find(Port.NAME, portName, ports); - assertNotNull("Port " + portName + " is not found", portData); - Asserts.assertPortAttributes(portData); - } - } - - public void testGetPort() throws Exception - { - List> ports = getJsonAsList("/rest/port/"); - assertNotNull("Ports data cannot be null", ports); - assertEquals("Unexpected number of ports", 2, ports.size()); - for (Map portMap : ports) - { - String portName = (String) portMap.get(Port.NAME); - assertNotNull("Port name attribute is not found", portName); - Map portData = getJsonAsSingletonList("/rest/port/" + URLDecoder.decode(portName, "UTF-8")); - assertNotNull("Port " + portName + " is not found", portData); - Asserts.assertPortAttributes(portData); - } - } - -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java deleted file mode 100644 index e83341de80..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QpidRestTestCase.java +++ /dev/null @@ -1,245 +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.management.plugin.servlet.rest; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.codehaus.jackson.JsonGenerationException; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.map.JsonMappingException; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; - -public class QpidRestTestCase extends QpidBrokerTestCase -{ - private static final Logger LOGGER = Logger.getLogger(QpidRestTestCase.class); - - public static final String[] EXPECTED_HOSTS = { "development", "test", "localhost" }; - public static final String[] EXPECTED_QUEUES = { "queue", "ping" }; - public static final String[] EXPECTED_EXCHANGES = { "amq.fanout", "amq.match", "amq.direct", "amq.topic", - "qpid.management", "<>" }; - - private int _httpPort; - private String _hostName; - private List _httpConnections; - - @Override - public void setUp() throws Exception - { - _httpConnections = new ArrayList(); - _hostName = InetAddress.getLocalHost().getHostName(); - _httpPort = findFreePort(); - customizeConfiguration(); - super.setUp(); - - } - - protected void customizeConfiguration() throws ConfigurationException, IOException - { - setConfigurationProperty("management.enabled", "false"); - setConfigurationProperty("management.http.enabled", "true"); - setConfigurationProperty("management.https.enabled", "false"); - setConfigurationProperty("management.http.port", Integer.toString(_httpPort)); - } - - public void teearDown() throws Exception - { - for (HttpURLConnection connection : _httpConnections) - { - try - { - connection.disconnect(); - } - catch (Exception e) - { - // ignore - } - } - super.tearDown(); - } - - protected int getHttpPort() - { - return _httpPort; - } - - protected String getHostName() - { - return _hostName; - } - - protected String getProtocol() - { - return "http"; - } - - protected String getManagementURL() - { - return getProtocol() + "://" + getHostName() + ":" + getHttpPort(); - } - - protected URL getManagementURL(String path) throws MalformedURLException - { - return new URL(getManagementURL() + path); - } - - protected HttpURLConnection openManagementConection(String path) throws IOException - { - URL url = getManagementURL(path); - HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - httpCon.setDoOutput(true); - return httpCon; - } - - protected HttpURLConnection openManagementConection(String path, String method) throws IOException - { - HttpURLConnection httpCon = openManagementConection(path); - httpCon.setRequestMethod(method); - return httpCon; - } - - protected List> readJsonResponseAsList(HttpURLConnection connection) throws IOException, - JsonParseException, JsonMappingException - { - byte[] data = readConnectionInputStream(connection); - - ObjectMapper mapper = new ObjectMapper(); - - TypeReference>> typeReference = new TypeReference>>() - { - }; - List> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); - return providedObject; - } - - protected Map readJsonResponseAsMap(HttpURLConnection connection) throws IOException, - JsonParseException, JsonMappingException - { - byte[] data = readConnectionInputStream(connection); - - ObjectMapper mapper = new ObjectMapper(); - - TypeReference> typeReference = new TypeReference>() - { - }; - Map providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference); - return providedObject; - } - - protected byte[] readConnectionInputStream(HttpURLConnection connection) throws IOException - { - InputStream is = connection.getInputStream(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int len = -1; - while ((len = is.read(buffer)) != -1) - { - baos.write(buffer, 0, len); - } - if (LOGGER.isTraceEnabled()) - { - LOGGER.trace("RESPONSE:" + new String(baos.toByteArray())); - } - return baos.toByteArray(); - } - - protected void writeJsonRequest(HttpURLConnection connection, Map data) throws JsonGenerationException, - JsonMappingException, IOException - { - ObjectMapper mapper = new ObjectMapper(); - mapper.writeValue(connection.getOutputStream(), data); - } - - protected Map find(String name, Object value, List> data) - { - for (Map map : data) - { - Object mapValue = map.get(name); - if (value.equals(mapValue)) - { - return map; - } - } - return null; - } - - protected Map find(Map searchAttributes, List> data) - { - for (Map map : data) - { - boolean equals = true; - for (Map.Entry entry : searchAttributes.entrySet()) - { - Object mapValue = map.get(entry.getKey()); - if (!entry.getValue().equals(mapValue)) - { - equals = false; - break; - } - } - if (equals) - { - return map; - } - } - return null; - } - - protected Map getJsonAsSingletonList(String path) throws IOException - { - List> response = getJsonAsList(path); - - assertNotNull("Response cannot be null", response); - assertEquals("Unexpected response", 1, response.size()); - return response.get(0); - } - - protected List> getJsonAsList(String path) throws IOException, JsonParseException, - JsonMappingException - { - HttpURLConnection connection = openManagementConection(path, "GET"); - connection.connect(); - List> response = readJsonResponseAsList(connection); - return response; - } - - protected Map getJsonAsMap(String path) throws IOException - { - HttpURLConnection connection = openManagementConection(path, "GET"); - connection.connect(); - Map response = readJsonResponseAsMap(connection); - return response; - } -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java deleted file mode 100644 index 5f11b3fb1d..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueRestTest.java +++ /dev/null @@ -1,225 +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.management.plugin.servlet.rest; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URLDecoder; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; - -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.Consumer; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.Queue; - -public class QueueRestTest extends QpidRestTestCase -{ - private static final String QUEUE_ATTRIBUTE_CONSUMERS = "consumers"; - private static final String QUEUE_ATTRIBUTE_BINDINGS = "bindings"; - - /** - * Message number to publish into queue - */ - private static final int MESSAGE_NUMBER = 2; - private static final int MESSAGE_PAYLOAD_SIZE = 6; - private static final int ENQUEUED_MESSAGES = 1; - private static final int DEQUEUED_MESSAGES = 1; - private static final int ENQUEUED_BYTES = MESSAGE_PAYLOAD_SIZE; - private static final int DEQUEUED_BYTES = MESSAGE_PAYLOAD_SIZE; - - private Connection _connection; - - public void setUp() throws Exception - { - super.setUp(); - _connection = getConnection(); - Session session = _connection.createSession(true, Session.SESSION_TRANSACTED); - String queueName = getTestQueueName(); - Destination queue = session.createQueue(queueName); - MessageConsumer consumer = session.createConsumer(queue); - MessageProducer producer = session.createProducer(queue); - - for (int i = 0; i < MESSAGE_NUMBER; i++) - { - producer.send(session.createTextMessage("Test-" + i)); - } - session.commit(); - _connection.start(); - Message m = consumer.receive(1000l); - assertNotNull("Message is not received", m); - session.commit(); - } - - public void testGetVirtualHostQueues() throws Exception - { - String queueName = getTestQueueName(); - List> queues = getJsonAsList("/rest/queue/test"); - assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length + 1, queues.size()); - String[] expectedQueues = new String[EXPECTED_QUEUES.length + 1]; - System.arraycopy(EXPECTED_QUEUES, 0, expectedQueues, 0, EXPECTED_QUEUES.length); - expectedQueues[EXPECTED_QUEUES.length] = queueName; - - for (String name : expectedQueues) - { - Map queueDetails = find(Queue.NAME, name, queues); - Asserts.assertQueue(name, "standard", queueDetails); - - @SuppressWarnings("unchecked") - List> bindings = (List>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS); - assertNotNull("Queue bindings are not found", bindings); - assertEquals("Unexpected number of bindings", 2, bindings.size()); - - Map defaultExchangeBinding = find(Binding.EXCHANGE, "<>", bindings); - Map directExchangeBinding = find(Binding.EXCHANGE, "amq.direct", bindings); - Asserts.assertBinding(name, "<>", defaultExchangeBinding); - Asserts.assertBinding(name, "amq.direct", directExchangeBinding); - } - } - - public void testGetByName() throws Exception - { - String queueName = getTestQueueName(); - Map queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); - Asserts.assertQueue(queueName, "standard", queueDetails); - assertStatistics(queueDetails); - - @SuppressWarnings("unchecked") - List> bindings = (List>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS); - assertNotNull("Queue bindings are not found", bindings); - assertEquals("Unexpected number of bindings", 2, bindings.size()); - - Map defaultExchangeBinding = find(Binding.EXCHANGE, "<>", bindings); - Map directExchangeBinding = find(Binding.EXCHANGE, "amq.direct", bindings); - Asserts.assertBinding(queueName, "<>", defaultExchangeBinding); - Asserts.assertBinding(queueName, "amq.direct", directExchangeBinding); - - @SuppressWarnings("unchecked") - List> consumers = (List>) queueDetails.get(QUEUE_ATTRIBUTE_CONSUMERS); - assertNotNull("Queue consumers are not found", consumers); - assertEquals("Unexpected number of consumers", 1, consumers.size()); - assertConsumer(consumers.get(0)); - } - - public void testPutCreateBinding() throws Exception - { - String queueName = getTestQueueName(); - String bindingName = queueName + 2; - String[] exchanges = { "amq.direct", "amq.fanout", "amq.topic", "amq.match", "qpid.management", "<>" }; - - for (int i = 0; i < exchanges.length; i++) - { - createBinding(bindingName, exchanges[i], queueName); - } - - Map queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); - Asserts.assertQueue(queueName, "standard", queueDetails); - - @SuppressWarnings("unchecked") - List> bindings = (List>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS); - assertNotNull("Queue bindings are not found", bindings); - assertEquals("Unexpected number of bindings", exchanges.length + 2, bindings.size()); - - Map searchAttributes = new HashMap(); - searchAttributes.put(Binding.NAME, bindingName); - - for (int i = 0; i < exchanges.length; i++) - { - searchAttributes.put(Binding.EXCHANGE, exchanges[i]); - Map binding = find(searchAttributes, bindings); - Asserts.assertBinding(bindingName, queueName, exchanges[i], binding); - } - } - - private void createBinding(String bindingName, String exchangeName, String queueName) throws IOException - { - HttpURLConnection connection = openManagementConection( - "/rest/binding/test/" + URLDecoder.decode(exchangeName, "UTF-8") + "/" + queueName + "/" + bindingName, - "PUT"); - - Map bindingData = new HashMap(); - bindingData.put(Binding.NAME, bindingName); - bindingData.put(Binding.EXCHANGE, exchangeName); - bindingData.put(Binding.QUEUE, queueName); - - writeJsonRequest(connection, bindingData); - assertEquals("Unexpected response code", 201, connection.getResponseCode()); - - connection.disconnect(); - } - - private void assertConsumer(Map consumer) - { - assertNotNull("Consumer map should not be null", consumer); - Asserts.assertAttributesPresent(consumer, Consumer.AVAILABLE_ATTRIBUTES, Consumer.STATE, Consumer.TIME_TO_LIVE, - Consumer.CREATED, Consumer.UPDATED, Consumer.SETTLEMENT_MODE, Consumer.EXCLUSIVE, Consumer.SELECTOR, - Consumer.NO_LOCAL); - - assertEquals("Unexpected binding attribute " + Consumer.NAME, "1", consumer.get(Consumer.NAME)); - assertEquals("Unexpected binding attribute " + Consumer.DURABLE, Boolean.FALSE, consumer.get(Consumer.DURABLE)); - assertEquals("Unexpected binding attribute " + Consumer.LIFETIME_POLICY, LifetimePolicy.AUTO_DELETE.name(), - consumer.get(Consumer.LIFETIME_POLICY)); - assertEquals("Unexpected binding attribute " + Consumer.DISTRIBUTION_MODE, "MOVE", - consumer.get(Consumer.DISTRIBUTION_MODE)); - - @SuppressWarnings("unchecked") - Map statistics = (Map) consumer.get(Asserts.STATISTICS_ATTRIBUTE); - assertNotNull("Consumer statistics is not present", statistics); - Asserts.assertAttributesPresent(statistics, Consumer.AVAILABLE_STATISTICS, Consumer.STATE_CHANGED); - } - - private void assertStatistics(Map queueDetails) - { - @SuppressWarnings("unchecked") - Map statistics = (Map) queueDetails.get(Asserts.STATISTICS_ATTRIBUTE); - assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES, - statistics.get(Queue.PERSISTENT_DEQUEUED_MESSAGES)); - assertEquals("Unexpected queue statistics attribute " + Queue.QUEUE_DEPTH_MESSAGES, ENQUEUED_MESSAGES, - statistics.get(Queue.QUEUE_DEPTH_MESSAGES)); - assertEquals("Unexpected queue statistics attribute " + Queue.CONSUMER_COUNT, 1, - statistics.get(Queue.CONSUMER_COUNT)); - assertEquals("Unexpected queue statistics attribute " + Queue.CONSUMER_COUNT_WITH_CREDIT, 1, - statistics.get(Queue.CONSUMER_COUNT_WITH_CREDIT)); - assertEquals("Unexpected queue statistics attribute " + Queue.BINDING_COUNT, 2, statistics.get(Queue.BINDING_COUNT)); - assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES, - statistics.get(Queue.PERSISTENT_DEQUEUED_MESSAGES)); - assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES, - statistics.get(Queue.TOTAL_DEQUEUED_MESSAGES)); - assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_DEQUEUED_BYTES, DEQUEUED_BYTES, - statistics.get(Queue.TOTAL_DEQUEUED_BYTES)); - assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_BYTES, DEQUEUED_BYTES, - statistics.get(Queue.TOTAL_DEQUEUED_BYTES)); - assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_ENQUEUED_BYTES, ENQUEUED_BYTES - + DEQUEUED_BYTES, statistics.get(Queue.PERSISTENT_ENQUEUED_BYTES)); - assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_ENQUEUED_BYTES, ENQUEUED_BYTES + DEQUEUED_BYTES, - statistics.get(Queue.TOTAL_ENQUEUED_BYTES)); - assertEquals("Unexpected queue statistics attribute " + Queue.QUEUE_DEPTH_BYTES, ENQUEUED_BYTES, - statistics.get(Queue.QUEUE_DEPTH_BYTES)); - } -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java deleted file mode 100644 index b504c9fa60..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslRestTest.java +++ /dev/null @@ -1,42 +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.management.plugin.servlet.rest; - -import java.util.List; -import java.util.Map; - -public class SaslRestTest extends QpidRestTestCase -{ - public void testGet() throws Exception - { - Map saslData = getJsonAsMap("/rest/sasl"); - assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms")); - - @SuppressWarnings("unchecked") - List mechanisms = (List) saslData.get("mechanisms"); - String[] expectedMechanisms = { "AMQPLAIN", "PLAIN", "CRAM-MD5" }; - for (String mechanism : expectedMechanisms) - { - assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism)); - } - } - -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java deleted file mode 100644 index b01e1d44b8..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/StructureRestTest.java +++ /dev/null @@ -1,115 +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.management.plugin.servlet.rest; - -import java.util.List; -import java.util.Map; - -public class StructureRestTest extends QpidRestTestCase -{ - - public void testGet() throws Exception - { - Map structure = getJsonAsMap("/rest/structure"); - assertNotNull("Structure data cannot be null", structure); - assertNode(structure, "Broker"); - - @SuppressWarnings("unchecked") - List> virtualhosts = (List>) structure.get("virtualhosts"); - assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size()); - - @SuppressWarnings("unchecked") - List> ports = (List>) structure.get("ports"); - assertEquals("Unexpected number of ports", 2, ports.size()); - - @SuppressWarnings("unchecked") - List> providers = (List>) structure.get("authenticationproviders"); - assertEquals("Unexpected number of authentication providers", 1, providers.size()); - - for (String hostName : EXPECTED_HOSTS) - { - Map host = find("name", hostName, virtualhosts); - assertNotNull("Host " + hostName + " is not found ", host); - assertNode(host, hostName); - - @SuppressWarnings("unchecked") - List> queues = (List>) host.get("queues"); - assertNotNull("Host " + hostName + " queues are not found ", queues); - for (String queueName : EXPECTED_QUEUES) - { - Map queue = find("name", queueName, queues); - assertNotNull(hostName + " queue " + queueName + " is not found ", queue); - assertNode(queue, queueName); - - @SuppressWarnings("unchecked") - List> bindings = (List>) queue.get("bindings"); - assertNotNull(hostName + " queue " + queueName + " bindings are not found ", queues); - for (Map binding : bindings) - { - assertNode(binding, queueName); - } - } - - @SuppressWarnings("unchecked") - List> exchanges = (List>) host.get("exchanges"); - assertNotNull("Host " + hostName + " exchanges are not found ", exchanges); - for (String exchangeName : EXPECTED_EXCHANGES) - { - Map exchange = find("name", exchangeName, exchanges); - assertNotNull("Exchange " + exchangeName + " is not found ", exchange); - assertNode(exchange, exchangeName); - if ("amq.direct".equalsIgnoreCase(exchangeName) || "<>".equalsIgnoreCase(exchangeName)) - { - @SuppressWarnings("unchecked") - List> bindings = (List>) exchange.get("bindings"); - assertNotNull(hostName + " exchange " + exchangeName + " bindings are not found ", bindings); - for (String queueName : EXPECTED_QUEUES) - { - Map binding = find("name", queueName, bindings); - assertNotNull(hostName + " exchange " + exchangeName + " binding " + queueName + " is not found", binding); - assertNode(binding, queueName); - } - } - } - - @SuppressWarnings("unchecked") - List> aliases = (List>) host.get("virtualhostaliases"); - assertNotNull("Host " + hostName + " aliaces are not found ", aliases); - assertEquals("Unexpected aliaces size", 1, aliases.size()); - assertNode(aliases.get(0), hostName); - } - - int[] expectedPorts = { getPort(), getHttpPort() }; - for (int port : expectedPorts) - { - String portName = "0.0.0.0:" + port; - Map portData = find("name", portName, ports); - assertNotNull("Port " + portName + " is not found ", portData); - assertNode(portData, portName); - } - } - - private void assertNode(Map node, String name) - { - assertEquals("Unexpected name", name, node.get("name")); - assertNotNull("Unexpected id", node.get("id")); - } -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java deleted file mode 100644 index e56fa27e21..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/UserRestTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.management.plugin.servlet.rest; - -import java.net.HttpURLConnection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.qpid.server.model.User; - -public class UserRestTest extends QpidRestTestCase -{ - public void testGet() throws Exception - { - List> users = getJsonAsList("/rest/user"); - assertNotNull("Users cannot be null", users); - assertTrue("Unexpected number of users", users.size() > 1); - for (Map user : users) - { - assertUser(user); - } - } - - public void testGetUserByName() throws Exception - { - List> users = getJsonAsList("/rest/user"); - assertNotNull("Users cannot be null", users); - assertTrue("Unexpected number of users", users.size() > 1); - for (Map user : users) - { - assertNotNull("Attribute " + User.ID, user.get(User.ID)); - String userName = (String) user.get(User.NAME); - assertNotNull("Attribute " + User.NAME, userName); - Map userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" - + userName); - assertUser(userDetails); - assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); - } - } - - public void testPut() throws Exception - { - String userName = getTestName(); - HttpURLConnection connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager/" - + userName, "PUT"); - - Map userData = new HashMap(); - userData.put(User.NAME, userName); - userData.put(User.PASSWORD, userName); - - writeJsonRequest(connection, userData); - assertEquals("Unexpected response code", 201, connection.getResponseCode()); - - connection.disconnect(); - - Map userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" - + userName); - assertUser(userDetails); - assertEquals("Unexpected user name", userName, userDetails.get(User.NAME)); - } - - public void testDelete() throws Exception - { - // add user - String userName = getTestName(); - HttpURLConnection connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager/" - + userName, "PUT"); - - Map userData = new HashMap(); - userData.put(User.NAME, userName); - userData.put(User.PASSWORD, userName); - - writeJsonRequest(connection, userData); - assertEquals("Unexpected response code", 201, connection.getResponseCode()); - connection.disconnect(); - - Map userDetails = getJsonAsSingletonList("/rest/user/PrincipalDatabaseAuthenticationManager/" - + userName); - String id = (String) userDetails.get(User.ID); - - connection = openManagementConection("/rest/user/PrincipalDatabaseAuthenticationManager?id=" + id, "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List> users = getJsonAsList("/rest/user/PrincipalDatabaseAuthenticationManager/" + userName); - assertEquals("User should be deleted", 0, users.size()); - } - - private void assertUser(Map user) - { - assertNotNull("Attribute " + User.ID, user.get(User.ID)); - assertNotNull("Attribute " + User.NAME, user.get(User.NAME)); - } -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java deleted file mode 100644 index 17f1aaaf7b..0000000000 --- a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/VirtualHostRestTest.java +++ /dev/null @@ -1,434 +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.management.plugin.servlet.rest; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.jms.Session; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.codehaus.jackson.JsonGenerationException; -import org.codehaus.jackson.map.JsonMappingException; - -public class VirtualHostRestTest extends QpidRestTestCase -{ - private static final String VIRTUALHOST_EXCHANGES_ATTRIBUTE = "exchanges"; - public static final String VIRTUALHOST_QUEUES_ATTRIBUTE = "queues"; - public static final String VIRTUALHOST_CONNECTIONS_ATTRIBUTE = "connections"; - - private AMQConnection _connection; - - public void testGet() throws Exception - { - List> hosts = getJsonAsList("/rest/virtualhost/"); - assertNotNull("Hosts data cannot be null", hosts); - assertEquals("Unexpected number of hosts", 3, hosts.size()); - for (String hostName : EXPECTED_HOSTS) - { - Map host = find("name", hostName, hosts); - Asserts.assertVirtualHost(hostName, host); - } - } - - public void testGetHost() throws Exception - { - // create AMQP connection to get connection JSON details - _connection = (AMQConnection) getConnection(); - _connection.createSession(true, Session.SESSION_TRANSACTED); - - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - Asserts.assertVirtualHost("test", hostDetails); - - @SuppressWarnings("unchecked") - Map statistics = (Map) hostDetails.get(Asserts.STATISTICS_ATTRIBUTE); - assertEquals("Unexpected number of exchanges in statistics", 6, statistics.get(VirtualHost.EXCHANGE_COUNT)); - assertEquals("Unexpected number of queues in statistics", 2, statistics.get(VirtualHost.QUEUE_COUNT)); - assertEquals("Unexpected number of connections in statistics", 1, statistics.get(VirtualHost.CONNECTION_COUNT)); - - @SuppressWarnings("unchecked") - List> exchanges = (List>) hostDetails.get(VIRTUALHOST_EXCHANGES_ATTRIBUTE); - assertEquals("Unexpected number of exchanges", 6, exchanges.size()); - Asserts.assertDurableExchange("amq.fanout", "fanout", find(Exchange.NAME, "amq.fanout", exchanges)); - Asserts.assertDurableExchange("qpid.management", "management", find(Exchange.NAME, "qpid.management", exchanges)); - Asserts.assertDurableExchange("amq.topic", "topic", find(Exchange.NAME, "amq.topic", exchanges)); - Asserts.assertDurableExchange("amq.direct", "direct", find(Exchange.NAME, "amq.direct", exchanges)); - Asserts.assertDurableExchange("amq.match", "headers", find(Exchange.NAME, "amq.match", exchanges)); - Asserts.assertDurableExchange("<>", "direct", find(Exchange.NAME, "<>", exchanges)); - - @SuppressWarnings("unchecked") - List> queues = (List>) hostDetails.get(VIRTUALHOST_QUEUES_ATTRIBUTE); - assertEquals("Unexpected number of queues", 2, queues.size()); - Map queue = find(Queue.NAME, "queue", queues); - Map ping = find(Queue.NAME, "ping", queues); - Asserts.assertQueue("queue", "standard", queue); - Asserts.assertQueue("ping", "standard", ping); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, queue.get(Queue.DURABLE)); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, ping.get(Queue.DURABLE)); - - @SuppressWarnings("unchecked") - List> connections = (List>) hostDetails - .get(VIRTUALHOST_CONNECTIONS_ATTRIBUTE); - assertEquals("Unexpected number of connections", 1, connections.size()); - Asserts.assertConnection(connections.get(0), _connection); - } - - public void testPutCreateQueue() throws Exception - { - String queueName = getTestQueueName(); - - createQueue(queueName + "-standard", "standard", null); - - Map sortedQueueAttributes = new HashMap(); - sortedQueueAttributes.put(Queue.SORT_KEY, "sortme"); - createQueue(queueName + "-sorted", "sorted", sortedQueueAttributes); - - Map priorityQueueAttributes = new HashMap(); - priorityQueueAttributes.put(Queue.PRIORITIES, 10); - createQueue(queueName + "-priority", "priority", priorityQueueAttributes); - - Map lvqQueueAttributes = new HashMap(); - lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ"); - createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes); - - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - - @SuppressWarnings("unchecked") - List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map standardQueue = find(Queue.NAME, queueName + "-standard" , queues); - Map sortedQueue = find(Queue.NAME, queueName + "-sorted" , queues); - Map priorityQueue = find(Queue.NAME, queueName + "-priority" , queues); - Map lvqQueue = find(Queue.NAME, queueName + "-lvq" , queues); - - Asserts.assertQueue(queueName + "-standard", "standard", standardQueue); - Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue); - Asserts.assertQueue(queueName + "-priority", "priority", priorityQueue); - Asserts.assertQueue(queueName + "-lvq", "lvq", lvqQueue); - - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, standardQueue.get(Queue.DURABLE)); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, sortedQueue.get(Queue.DURABLE)); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE)); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE)); - - assertEquals("Unexpected sorted key attribute", "sortme", sortedQueue.get(Queue.SORT_KEY)); - assertEquals("Unexpected lvq key attribute", "LVQ", lvqQueue.get(Queue.LVQ_KEY)); - assertEquals("Unexpected priorities key attribute", 10, priorityQueue.get(Queue.PRIORITIES)); - } - - public void testPutCreateExchange() throws Exception - { - String exchangeName = getTestName(); - - createExchange(exchangeName + "-direct", "direct"); - createExchange(exchangeName + "-topic", "topic"); - createExchange(exchangeName + "-headers", "headers"); - createExchange(exchangeName + "-fanout", "fanout"); - - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - - @SuppressWarnings("unchecked") - List> exchanges = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); - Map directExchange = find(Queue.NAME, exchangeName + "-direct" , exchanges); - Map topicExchange = find(Queue.NAME, exchangeName + "-topic" , exchanges); - Map headersExchange = find(Queue.NAME, exchangeName + "-headers" , exchanges); - Map fanoutExchange = find(Queue.NAME, exchangeName + "-fanout" , exchanges); - - Asserts.assertDurableExchange(exchangeName + "-direct", "direct", directExchange); - Asserts.assertDurableExchange(exchangeName + "-topic", "topic", topicExchange); - Asserts.assertDurableExchange(exchangeName + "-headers", "headers", headersExchange); - Asserts.assertDurableExchange(exchangeName + "-fanout", "fanout", fanoutExchange); - - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, directExchange.get(Queue.DURABLE)); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, topicExchange.get(Queue.DURABLE)); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, headersExchange.get(Queue.DURABLE)); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, fanoutExchange.get(Queue.DURABLE)); - - } - - public void testPutCreateLVQWithoutKey() throws Exception - { - String queueName = getTestQueueName()+ "-lvq"; - createQueue(queueName, "lvq", null); - - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - - @SuppressWarnings("unchecked") - List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map lvqQueue = find(Queue.NAME, queueName , queues); - - Asserts.assertQueue(queueName , "lvq", lvqQueue); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE)); - assertEquals("Unexpected lvq key attribute", AMQQueueFactory.QPID_LVQ_KEY, lvqQueue.get(Queue.LVQ_KEY)); - } - - public void testPutCreateSortedQueueWithoutKey() throws Exception - { - String queueName = getTestQueueName() + "-sorted"; - int responseCode = tryCreateQueue(queueName, "sorted", null); - assertEquals("Unexpected response code", 409, responseCode); - - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - - @SuppressWarnings("unchecked") - List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map testQueue = find(Queue.NAME, queueName , queues); - - assertNull("Sorted queue without a key was created ", testQueue); - } - - public void testPutCreatePriorityQueueWithoutKey() throws Exception - { - String queueName = getTestQueueName()+ "-priority"; - createQueue(queueName, "priority", null); - - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - - @SuppressWarnings("unchecked") - List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map priorityQueue = find(Queue.NAME, queueName , queues); - - Asserts.assertQueue(queueName , "priority", priorityQueue); - assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE)); - assertEquals("Unexpected number of priorities", 10, priorityQueue.get(Queue.PRIORITIES)); - } - - public void testPutCreateStandardQueueWithoutType() throws Exception - { - String queueName = getTestQueueName(); - createQueue(queueName, null, null); - - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - - @SuppressWarnings("unchecked") - List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map queue = find(Queue.NAME, queueName , queues); - - Asserts.assertQueue(queueName , "standard", queue); - } - - public void testPutCreateQueueOfUnsupportedType() throws Exception - { - String queueName = getTestQueueName(); - int responseCode = tryCreateQueue(queueName, "unsupported", null); - assertEquals("Unexpected response code", 409, responseCode); - - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - - @SuppressWarnings("unchecked") - List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map queue = find(Queue.NAME, queueName , queues); - - assertNull("Queue of unsupported type was created", queue); - } - - public void testDeleteQueue() throws Exception - { - String queueName = getTestQueueName(); - createQueue(queueName, null, null); - - HttpURLConnection connection = openManagementConection("/rest/queue/test/" + queueName, "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List> queues = getJsonAsList("/rest/queue/test/" + queueName); - assertEquals("Queue should be deleted", 0, queues.size()); - } - - public void testDeleteQueueById() throws Exception - { - String queueName = getTestQueueName(); - createQueue(queueName, null, null); - Map queueDetails = getJsonAsSingletonList("/rest/queue/test/" + queueName); - - HttpURLConnection connection = openManagementConection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List> queues = getJsonAsList("/rest/queue/test/" + queueName); - assertEquals("Queue should be deleted", 0, queues.size()); - } - - public void testDeleteExchange() throws Exception - { - String exchangeName = getTestName(); - createExchange(exchangeName, "direct"); - - HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List> queues = getJsonAsList("/rest/exchange/test/" + exchangeName); - assertEquals("Exchange should be deleted", 0, queues.size()); - } - - public void testDeleteExchangeById() throws Exception - { - String exchangeName = getTestName(); - createExchange(exchangeName, "direct"); - Map echangeDetails = getJsonAsSingletonList("/rest/exchange/test/" + exchangeName); - - HttpURLConnection connection = openManagementConection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List> queues = getJsonAsList("/rest/exchange/test/" + exchangeName); - assertEquals("Exchange should be deleted", 0, queues.size()); - } - - public void testPutCreateQueueWithAttributes() throws Exception - { - String queueName = getTestQueueName(); - - Map attributes = new HashMap(); - attributes.put(Queue.ALERT_REPEAT_GAP, 1000); - attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, 3600000); - attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, 1000000000); - attributes.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 800); - attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 15); - attributes.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 2000000000); - attributes.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 1500000000); - - createQueue(queueName + "-standard", "standard", attributes); - - Map sortedQueueAttributes = new HashMap(); - sortedQueueAttributes.putAll(attributes); - sortedQueueAttributes.put(Queue.SORT_KEY, "sortme"); - createQueue(queueName + "-sorted", "sorted", sortedQueueAttributes); - - Map priorityQueueAttributes = new HashMap(); - priorityQueueAttributes.putAll(attributes); - priorityQueueAttributes.put(Queue.PRIORITIES, 10); - createQueue(queueName + "-priority", "priority", priorityQueueAttributes); - - Map lvqQueueAttributes = new HashMap(); - lvqQueueAttributes.putAll(attributes); - lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ"); - createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes); - - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - - @SuppressWarnings("unchecked") - List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - Map standardQueue = find(Queue.NAME, queueName + "-standard" , queues); - Map sortedQueue = find(Queue.NAME, queueName + "-sorted" , queues); - Map priorityQueue = find(Queue.NAME, queueName + "-priority" , queues); - Map lvqQueue = find(Queue.NAME, queueName + "-lvq" , queues); - - attributes.put(Queue.DURABLE, Boolean.TRUE); - Asserts.assertQueue(queueName + "-standard", "standard", standardQueue, attributes); - Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue, attributes); - Asserts.assertQueue(queueName + "-priority", "priority", priorityQueue, attributes); - Asserts.assertQueue(queueName + "-lvq", "lvq", lvqQueue, attributes); - - assertEquals("Unexpected sorted key attribute", "sortme", sortedQueue.get(Queue.SORT_KEY)); - assertEquals("Unexpected lvq key attribute", "LVQ", lvqQueue.get(Queue.LVQ_KEY)); - assertEquals("Unexpected priorities key attribute", 10, priorityQueue.get(Queue.PRIORITIES)); - } - - @SuppressWarnings("unchecked") - public void testCreateQueueWithDLQEnabled() throws Exception - { - String queueName = getTestQueueName(); - - Map attributes = new HashMap(); - attributes.put(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); - - //verify the starting state - Map hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - List> exchanges = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); - - assertNull("queue should not have already been present", find(Queue.NAME, queueName , queues)); - assertNull("queue should not have already been present", find(Queue.NAME, queueName + "_DLQ" , queues)); - assertNull("exchange should not have already been present", find(Exchange.NAME, queueName + "_DLE" , exchanges)); - - //create the queue - createQueue(queueName, "standard", attributes); - - //verify the new queue, as well as the DLQueue and DLExchange have been created - hostDetails = getJsonAsSingletonList("/rest/virtualhost/test"); - queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE); - exchanges = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE); - - Map queue = find(Queue.NAME, queueName , queues); - Map dlqQueue = find(Queue.NAME, queueName + "_DLQ" , queues); - Map dlExchange = find(Exchange.NAME, queueName + "_DLE" , exchanges); - assertNotNull("queue should not have been present", queue); - assertNotNull("queue should not have been present", dlqQueue); - assertNotNull("exchange should not have been present", dlExchange); - - //verify that the alternate exchange is set as expected on the new queue - Map queueAttributes = new HashMap(); - queueAttributes.put(Queue.ALTERNATE_EXCHANGE, queueName + "_DLE"); - - Asserts.assertQueue(queueName, "standard", queue, queueAttributes); - Asserts.assertQueue(queueName, "standard", queue, null); - } - - private void createExchange(String exchangeName, String exchangeType) throws IOException - { - HttpURLConnection connection = openManagementConection("/rest/exchange/test/" + exchangeName, "PUT"); - - Map queueData = new HashMap(); - queueData.put(Exchange.NAME, exchangeName); - queueData.put(Exchange.DURABLE, Boolean.TRUE); - queueData.put(Exchange.TYPE, exchangeType); - - writeJsonRequest(connection, queueData); - assertEquals("Unexpected response code", 201, connection.getResponseCode()); - - connection.disconnect(); - } - - private void createQueue(String queueName, String queueType, Map attributes) throws IOException, - JsonGenerationException, JsonMappingException - { - int responseCode = tryCreateQueue(queueName, queueType, attributes); - assertEquals("Unexpected response code", 201, responseCode); - } - - private int tryCreateQueue(String queueName, String queueType, Map attributes) throws IOException, - JsonGenerationException, JsonMappingException - { - HttpURLConnection connection = openManagementConection("/rest/queue/test/" + queueName, "PUT"); - - Map queueData = new HashMap(); - queueData.put(Queue.NAME, queueName); - queueData.put(Queue.DURABLE, Boolean.TRUE); - if (queueType != null) - { - queueData.put(Queue.TYPE, queueType); - } - if (attributes != null) - { - queueData.putAll(attributes); - } - - writeJsonRequest(connection, queueData); - int responseCode = connection.getResponseCode(); - connection.disconnect(); - return responseCode; - } - -} diff --git a/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/session/LoginLogoutReporterTest.java b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/session/LoginLogoutReporterTest.java new file mode 100644 index 0000000000..1d43c44587 --- /dev/null +++ b/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/session/LoginLogoutReporterTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.plugin.session; + +import static org.mockito.Mockito.verify; +import static org.mockito.Matchers.argThat; + +import javax.security.auth.Subject; + +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogMessage; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.mockito.ArgumentMatcher; +import org.mockito.Mockito; + +import junit.framework.TestCase; + +public class LoginLogoutReporterTest extends TestCase +{ + private LoginLogoutReporter _loginLogoutReport; + private Subject _subject = new Subject(); + private LogActor _logActor = Mockito.mock(LogActor.class); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _subject.getPrincipals().add(new AuthenticatedPrincipal("mockusername")); + _loginLogoutReport = new LoginLogoutReporter(_logActor, _subject); + } + + public void testLoginLogged() + { + _loginLogoutReport.valueBound(null); + verify(_logActor).message(isLogMessageWithMessage("MNG-1007 : Open : User mockusername")); + } + + public void testLogoutLogged() + { + _loginLogoutReport.valueUnbound(null); + verify(_logActor).message(isLogMessageWithMessage("MNG-1008 : Close : User mockusername")); + } + + private LogMessage isLogMessageWithMessage(final String expectedMessage) + { + return argThat( new ArgumentMatcher() + { + @Override + public boolean matches(Object argument) + { + LogMessage actual = (LogMessage) argument; + return actual.toString().equals(expectedMessage); + } + }); + } +} diff --git a/java/broker-plugins/management-jmx/MANIFEST.MF b/java/broker-plugins/management-jmx/MANIFEST.MF deleted file mode 100644 index b18ec1ace7..0000000000 --- a/java/broker-plugins/management-jmx/MANIFEST.MF +++ /dev/null @@ -1,66 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Qpid Broker-Plugins Management JMX -Bundle-SymbolicName: broker-plugins-management-jmx -Bundle-Description: JMX management plugin for Qpid. -Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt -Bundle-DocURL: http://www.apache.org/ -Bundle-Version: 1.0.0 -Bundle-Activator: org.apache.qpid.server.jmx.JMXActivator -Bundle-RequiredExecutionEnvironment: JavaSE-1.6 -Bundle-ClassPath: . -Bundle-ActivationPolicy: lazy -Import-Package: org.apache.qpid, - org.apache.qpid.framing, - org.apache.qpid.protocol, - org.apache.qpid.common, - org.apache.qpid.management.common.mbeans, - org.apache.qpid.management.common.mbeans.annotations, - org.apache.qpid.server.security.auth, - org.apache.qpid.server.security.auth.manager, - org.apache.qpid.server.security.auth.rmi, - org.apache.qpid.server.security.auth.sasl, - org.apache.qpid.server.binding, - org.apache.qpid.server.exchange, - org.apache.qpid.server.logging, - org.apache.qpid.server.logging.log4j, - org.apache.qpid.server.logging.actors, - org.apache.qpid.server.logging.messages, - org.apache.qpid.server.message, - org.apache.qpid.server.model, - org.apache.qpid.server.model.adapter, - org.apache.qpid.server.model.impl, - org.apache.qpid.server.configuration, - org.apache.qpid.server.configuration.plugins, - org.apache.qpid.server.connection, - org.apache.qpid.server.plugins, - org.apache.qpid.server.protocol, - org.apache.qpid.server.queue, - org.apache.qpid.server.registry, - org.apache.qpid.server.security, - org.apache.qpid.server.security.access, - org.apache.qpid.server.stats, - org.apache.qpid.server.virtualhost, - org.apache.qpid.util, - org.apache.commons.codec;version=1.3.0, - org.apache.commons.codec.binary;version=1.3.0, - org.apache.commons.configuration;version=1.0.0, - org.apache.commons.lang;version=1.0.0, - org.apache.commons.lang.builder;version=1.0.0, - org.apache.commons.lang.time;version=1.0.0, - org.apache.log4j;version=1.2.16, - org.codehaus.jackson;version=1.9.0, - org.codehaus.jackson.map;version=1.9.0, - javax.management.remote.rmi, - javax.management.remote, - javax.servlet, - javax.servlet.http, - javax.management;version=1.0.0, - javax.management.monitor;version=1.0.0, - javax.management.openmbean;version=1.0.0, - javax.security.auth.login;version=1.0.0, - javax.security.auth;version=1.0.0, - javax.rmi.ssl;version=1.0.0, - org.osgi.util.tracker;version=1.0.0, - org.osgi.framework;version=1.3 -Export-Package: org.apache.qpid.server.jmx;uses:="org.osgi.framework" diff --git a/java/broker-plugins/management-jmx/build.xml b/java/broker-plugins/management-jmx/build.xml index fa50b8467d..9d212cf39a 100644 --- a/java/broker-plugins/management-jmx/build.xml +++ b/java/broker-plugins/management-jmx/build.xml @@ -17,28 +17,14 @@ - under the License. --> - - - - - - - - - - - - - - - + - - + + diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.java new file mode 100644 index 0000000000..b7aab78e45 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/CustomRMIServerSocketFactory.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.jmx; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.rmi.server.RMIServerSocketFactory; + +/** + * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry. + * Supplied to the registry at creation, this will prevent RMI-based operations on the + * registry such as attempting to bind a new object, thereby securing it from tampering. + * This is accomplished by always returning null when attempting to determine the address + * of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc + * made using the object reference will not be affected and continue to operate normally. + */ +class CustomRMIServerSocketFactory implements RMIServerSocketFactory +{ + + public ServerSocket createServerSocket(int port) throws IOException + { + return new NoLocalAddressServerSocket(port); + } + + private static class NoLocalAddressServerSocket extends ServerSocket + { + NoLocalAddressServerSocket(int port) throws IOException + { + super(port); + } + + @Override + public Socket accept() throws IOException + { + Socket s = new NoLocalAddressSocket(); + super.implAccept(s); + return s; + } + } + + private static class NoLocalAddressSocket extends Socket + { + @Override + public InetAddress getInetAddress() + { + return null; + } + } +} \ No newline at end of file diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java deleted file mode 100644 index c588b40de7..0000000000 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXActivator.java +++ /dev/null @@ -1,136 +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.jmx; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; - -public class JMXActivator implements BundleActivator -{ - private static final Logger LOGGER = Logger.getLogger(JMXActivator.class); - - private String _bundleName; - private JMXService _jmxService; - - private List _registeredServices; - - - public void start(final BundleContext ctx) throws Exception - { - boolean jmxManagementEnabled = ApplicationRegistry.getInstance().getConfiguration().getJMXManagementEnabled(); - - if (jmxManagementEnabled) - { - _jmxService = new JMXService(); - startJmsService(_jmxService); - - _bundleName = ctx.getBundle().getSymbolicName(); - - _registeredServices = registerServices(ctx); - } - else - { - LOGGER.debug("Skipping registration of JMX plugin as JMX Management disabled in config. "); - } - } - - public void stop(final BundleContext bundleContext) throws Exception - { - try - { - if (_jmxService != null) - { - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Stopping jmx plugin: " + _bundleName); - } - _jmxService.close(); - } - - if (_registeredServices != null) - { - unregisterServices(); - } - } - finally - { - _jmxService = null; - _registeredServices = null; - } - } - - - private List registerServices(BundleContext ctx) - { - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Registering jmx plugin: " + _bundleName); - } - - List serviceRegistrations = new ArrayList(); - - ServiceRegistration jmxServiceRegistration = ctx.registerService(JMXService.class.getName(), _jmxService, null); - ServiceRegistration jmxConfigFactoryRegistration = ctx.registerService(ConfigurationPluginFactory.class.getName(), JMXConfiguration.FACTORY, null); - - serviceRegistrations.add(jmxServiceRegistration); - serviceRegistrations.add(jmxConfigFactoryRegistration); - return serviceRegistrations; - } - - private void startJmsService(JMXService jmxService) throws Exception - { - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Starting JMX service"); - } - boolean startedSuccessfully = false; - try - { - jmxService.start(); - startedSuccessfully = true; - } - finally - { - if (!startedSuccessfully) - { - LOGGER.error("JMX failed to start normally, closing service"); - jmxService.close(); - } - } - } - - private void unregisterServices() - { - for (Iterator iterator = _registeredServices.iterator(); iterator.hasNext();) - { - ServiceRegistration service = iterator.next(); - service.unregister(); - } - } -} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java deleted file mode 100644 index dc9a712f90..0000000000 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXConfiguration.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; - -import java.util.Arrays; -import java.util.List; - -public class JMXConfiguration extends ConfigurationPlugin -{ - CompositeConfiguration _finalConfig; - - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - ConfigurationPlugin instance = new JMXConfiguration(); - instance.setConfiguration(path, config); - return instance; - } - - public List getParentPaths() - { - return Arrays.asList("jmx"); - } - }; - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - - public Configuration getConfiguration() - { - return _finalConfig; - } - - - @Override - public void validateConfiguration() throws ConfigurationException - { - // Valid Configuration either has xml links to new files - _finalConfig = new CompositeConfiguration(getConfig()); - List subFiles = getConfig().getList("xml[@fileName]"); - for (Object subFile : subFiles) - { - _finalConfig.addConfiguration(new XMLConfiguration((String) subFile)); - } - - } - -} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java index 0648235077..a045683de1 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java @@ -20,171 +20,114 @@ */ package org.apache.qpid.server.jmx; -import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; - -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; import javax.management.JMException; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationFilterSupport; -import javax.management.NotificationListener; import javax.management.ObjectName; -import javax.management.remote.JMXConnectionNotification; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXServiceURL; import javax.management.remote.MBeanServerForwarder; -import javax.management.remote.rmi.RMIConnection; import javax.management.remote.rmi.RMIConnectorServer; -import javax.management.remote.rmi.RMIJRMPServerImpl; -import javax.management.remote.rmi.RMIServerImpl; import javax.rmi.ssl.SslRMIClientSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; -import javax.security.auth.Subject; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.lang.management.ManagementFactory; -import java.lang.reflect.Proxy; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; import java.net.UnknownHostException; import java.rmi.AlreadyBoundException; import java.rmi.NoSuchObjectException; import java.rmi.NotBoundException; +import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.UnicastRemoteObject; import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; /** - * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no + * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no * security features implemented like user authentication and authorisation. */ public class JMXManagedObjectRegistry implements ManagedObjectRegistry { private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class); + private static final String OPERATIONAL_LOGGING_NAME = "JMX"; + private final MBeanServer _mbeanServer; + private JMXConnectorServer _cs; private Registry _rmiRegistry; - private boolean _useCustomSocketFactory; - private final int _jmxPortRegistryServer; - private final int _jmxPortConnectorServer; + private final Broker _broker; + private final Port _registryPort; + private final Port _connectorPort; - public JMXManagedObjectRegistry() throws AMQException + public JMXManagedObjectRegistry( + Broker broker, + Port connectorPort, Port registryPort, + JMXManagement jmxManagement) { - _log.info("Initialising managed object registry using platform MBean server"); - IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); + _broker = broker; + _registryPort = registryPort; + _connectorPort = connectorPort; - // Retrieve the config parameters - _useCustomSocketFactory = appRegistry.getConfiguration().getUseCustomRMISocketFactory(); - boolean platformServer = appRegistry.getConfiguration().getPlatformMbeanserver(); + boolean usePlatformServer = (Boolean)jmxManagement.getAttribute(JMXManagement.USE_PLATFORM_MBEAN_SERVER); _mbeanServer = - platformServer ? ManagementFactory.getPlatformMBeanServer() + usePlatformServer ? ManagementFactory.getPlatformMBeanServer() : MBeanServerFactory.createMBeanServer(ManagedObject.DOMAIN); + } - _jmxPortRegistryServer = appRegistry.getConfiguration().getJMXPortRegistryServer(); - _jmxPortConnectorServer = appRegistry.getConfiguration().getJMXConnectorServerPort(); - - } - - public void start() throws IOException, ConfigurationException + @Override + public void start() throws IOException { - - CurrentActor.get().message(ManagementConsoleMessages.STARTUP()); + CurrentActor.get().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME)); //check if system properties are set to use the JVM's out-of-the-box JMXAgent if (areOutOfTheBoxJMXOptionsSet()) { - CurrentActor.get().message(ManagementConsoleMessages.READY(true)); - return; + CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME)); } + else + { + startRegistryAndConnector(); + } + } - IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); - - - //Socket factories for the RMIConnectorServer, either default or SLL depending on configuration + private void startRegistryAndConnector() throws IOException + { + //Socket factories for the RMIConnectorServer, either default or SSL depending on configuration RMIClientSocketFactory csf; RMIServerSocketFactory ssf; - //check ssl enabled option in config, default to true if option is not set - boolean sslEnabled = appRegistry.getConfiguration().getManagementSSLEnabled(); + //check ssl enabled option on connector port (note we don't provide ssl for registry server at + //moment). + boolean connectorSslEnabled = _connectorPort.getTransports().contains(Transport.SSL); - if (sslEnabled) + if (connectorSslEnabled) { - //set the SSL related system properties used by the SSL RMI socket factories to the values - //given in the configuration file, unless command line settings have already been specified - String keyStorePath; + String keyStorePath = System.getProperty("javax.net.ssl.keyStore"); + String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword"); - if(System.getProperty("javax.net.ssl.keyStore") != null) - { - keyStorePath = System.getProperty("javax.net.ssl.keyStore"); - } - else - { - keyStorePath = appRegistry.getConfiguration().getManagementKeyStorePath(); - } + validateKeyStoreProperties(keyStorePath, keyStorePassword); - //check the keystore path value is valid - if (keyStorePath == null) - { - throw new ConfigurationException("JMX management SSL keystore path not defined, " + - "unable to start SSL protected JMX ConnectorServer"); - } - else - { - //ensure the system property is set - System.setProperty("javax.net.ssl.keyStore", keyStorePath); - - //check the file is usable - File ksf = new File(keyStorePath); - - if (!ksf.exists()) - { - throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf); - } - if (!ksf.canRead()) - { - throw new FileNotFoundException("Cannot read JMX management SSL keystore file: " - + ksf + ". Check permissions."); - } - - CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(ksf.getAbsolutePath())); - } - - //check the key store password is set - if (System.getProperty("javax.net.ssl.keyStorePassword") == null) - { - - if (appRegistry.getConfiguration().getManagementKeyStorePassword() == null) - { - throw new ConfigurationException("JMX management SSL keystore password not defined, " + - "unable to start requested SSL protected JMX server"); - } - else - { - System.setProperty("javax.net.ssl.keyStorePassword", - appRegistry.getConfiguration().getManagementKeyStorePassword()); - } - } + CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(keyStorePath)); //create the SSL RMI socket factories csf = new SslRMIClientSocketFactory(); @@ -197,27 +140,23 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry ssf = null; } + int jmxPortRegistryServer = _registryPort.getPort(); + int jmxPortConnectorServer = _connectorPort.getPort(); + //add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server - RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(_jmxPortRegistryServer)); - HashMap env = new HashMap(); - env.put(JMXConnectorServer.AUTHENTICATOR, rmipa); + RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(_broker, new InetSocketAddress(jmxPortConnectorServer)); + HashMap connectorEnv = new HashMap(); + connectorEnv.put(JMXConnectorServer.AUTHENTICATOR, rmipa); + + System.setProperty("java.rmi.server.randomIDs", "true"); + boolean useCustomSocketFactory = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, Boolean.TRUE.toString())); /* * Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub. * Using custom socket factory to prevent anyone (including us unfortunately) binding to the registry using RMI. * As a result, only binds made using the object reference will succeed, thus securing it from external change. */ - System.setProperty("java.rmi.server.randomIDs", "true"); - if(_useCustomSocketFactory) - { - _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, new CustomRMIServerSocketFactory()); - } - else - { - _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null); - } - - CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer)); + _rmiRegistry = createRmiRegistry(jmxPortRegistryServer, useCustomSocketFactory); /* * We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls @@ -225,57 +164,16 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry * locked it from any RMI based modifications, including our own. Instead, we will manually bind * the RMIConnectorServer stub to the registry using its object reference, which will still succeed. * - * The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer - * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's. + * The registry is exported on the defined management port 'port'. */ - final Map connectionIdUsernameMap = new ConcurrentHashMap(); - final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env) - { - - /** - * Override makeClient so we can cache the username of the client in a Map keyed by connectionId. - * ConnectionId is guaranteed to be unique per client connection, according to the JMS spec. - * An instance of NotificationListener (mapCleanupListener) will be responsible for removing these Map - * entries. - * - * @see javax.management.remote.rmi.RMIJRMPServerImpl#makeClient(String, javax.security.auth.Subject) - */ - @Override - protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException - { - final RMIConnection makeClient = super.makeClient(connectionId, subject); - final UsernamePrincipal usernamePrincipalFromSubject = UsernamePrincipal.getUsernamePrincipalFromSubject(subject); - connectionIdUsernameMap.put(connectionId, usernamePrincipalFromSubject.getName()); - return makeClient; - } - }; - - // Create a Listener responsible for removing the map entries add by the #makeClient entry above. - final NotificationListener mapCleanupListener = new NotificationListener() - { - - public void handleNotification(Notification notification, Object handback) - { - final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); - connectionIdUsernameMap.remove(connectionId); - } - }; + final UsernameCachingRMIJRMPServer usernameCachingRmiServer = new UsernameCachingRMIJRMPServer(jmxPortConnectorServer, csf, ssf, connectorEnv); - String localHost; - try - { - localHost = InetAddress.getLocalHost().getHostName(); - } - catch(UnknownHostException ex) - { - localHost="127.0.0.1"; - } - final String hostname = localHost; + final String localHostName = getLocalhost(); final JMXServiceURL externalUrl = new JMXServiceURL( - "service:jmx:rmi://"+hostname+":"+(_jmxPortConnectorServer)+"/jndi/rmi://"+hostname+":"+_jmxPortRegistryServer+"/jmxrmi"); + "service:jmx:rmi://"+localHostName+":"+(jmxPortConnectorServer)+"/jndi/rmi://"+localHostName+":"+jmxPortRegistryServer+"/jmxrmi"); - final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer); - _cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer) + final JMXServiceURL internalUrl = new JMXServiceURL("rmi", localHostName, jmxPortConnectorServer); + _cs = new RMIConnectorServer(internalUrl, connectorEnv, usernameCachingRmiServer, _mbeanServer) { @Override public synchronized void start() throws IOException @@ -283,7 +181,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry try { //manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent - _rmiRegistry.bind("jmxrmi", rmiConnectorServerStub); + _rmiRegistry.bind("jmxrmi", usernameCachingRmiServer); } catch (AlreadyBoundException abe) { @@ -311,7 +209,6 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry } catch (NotBoundException nbe) { - // TODO consider if we want to keep new logging _log.error("Failed to unbind jmxrmi", nbe); //ignore } @@ -326,97 +223,100 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry //must return our pre-crafted url that includes the full details, inc JNDI details return externalUrl; } - }; - //Add the custom invoker as an MBeanServerForwarder, and start the RMIConnectorServer. - MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance(); + MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance(_broker); _cs.setMBeanServerForwarder(mbsf); + // Install a ManagementLogonLogoffReporter so we can report as users logon/logoff + ManagementLogonLogoffReporter jmxManagementUserLogonLogoffReporter = new ManagementLogonLogoffReporter(_broker.getRootMessageLogger(), usernameCachingRmiServer); + _cs.addNotificationListener(jmxManagementUserLogonLogoffReporter, jmxManagementUserLogonLogoffReporter, null); - // Get the handler that is used by the above MBInvocationHandler Proxy. - // which is the MBeanInvocationHandlerImpl and so also a NotificationListener. - final NotificationListener invocationHandler = (NotificationListener) Proxy.getInvocationHandler(mbsf); - - // Install a notification listener on OPENED, CLOSED, and FAILED, - // passing the map of connection-ids to usernames as hand-back data. - final NotificationFilterSupport invocationHandlerFilter = new NotificationFilterSupport(); - invocationHandlerFilter.enableType(JMXConnectionNotification.OPENED); - invocationHandlerFilter.enableType(JMXConnectionNotification.CLOSED); - invocationHandlerFilter.enableType(JMXConnectionNotification.FAILED); - _cs.addNotificationListener(invocationHandler, invocationHandlerFilter, connectionIdUsernameMap); - - // Install a second notification listener on CLOSED AND FAILED only to remove the entry from the - // Map. Here we rely on the fact that JMX will call the listeners in the order in which they are - // installed. - final NotificationFilterSupport mapCleanupHandlerFilter = new NotificationFilterSupport(); - mapCleanupHandlerFilter.enableType(JMXConnectionNotification.CLOSED); - mapCleanupHandlerFilter.enableType(JMXConnectionNotification.FAILED); - _cs.addNotificationListener(mapCleanupListener, mapCleanupHandlerFilter, null); + // Install the usernameCachingRmiServer as a listener so it may cleanup as clients disconnect + _cs.addNotificationListener(usernameCachingRmiServer, usernameCachingRmiServer, null); _cs.start(); - String connectorServer = (sslEnabled ? "SSL " : "") + "JMX RMIConnectorServer"; - CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, _jmxPortConnectorServer)); - - CurrentActor.get().message(ManagementConsoleMessages.READY(false)); + String connectorServer = (connectorSslEnabled ? "SSL " : "") + "JMX RMIConnectorServer"; + CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, jmxPortConnectorServer)); + CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME)); } - /* - * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry. - * Supplied to the registry at creation, this will prevent RMI-based operations on the - * registry such as attempting to bind a new object, thereby securing it from tampering. - * This is accomplished by always returning null when attempting to determine the address - * of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc - * made using the object reference will not be affected and continue to operate normally. - */ - - private static class CustomRMIServerSocketFactory implements RMIServerSocketFactory + private Registry createRmiRegistry(int jmxPortRegistryServer, boolean useCustomRmiRegistry) + throws RemoteException { - - public ServerSocket createServerSocket(int port) throws IOException + Registry rmiRegistry; + if(useCustomRmiRegistry) { - return new NoLocalAddressServerSocket(port); + _log.debug("Using custom RMIServerSocketFactory"); + rmiRegistry = LocateRegistry.createRegistry(jmxPortRegistryServer, null, new CustomRMIServerSocketFactory()); } - - private static class NoLocalAddressServerSocket extends ServerSocket + else { - NoLocalAddressServerSocket(int port) throws IOException - { - super(port); - } + _log.debug("Using default RMIServerSocketFactory"); + rmiRegistry = LocateRegistry.createRegistry(jmxPortRegistryServer, null, null); + } - @Override - public Socket accept() throws IOException - { - Socket s = new NoLocalAddressSocket(); - super.implAccept(s); - return s; - } + CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", jmxPortRegistryServer)); + return rmiRegistry; + } + + private void validateKeyStoreProperties(String keyStorePath, String keyStorePassword) throws FileNotFoundException + { + if (keyStorePath == null) + { + throw new IllegalConfigurationException("JVM system property 'javax.net.ssl.keyStore' is not set, " + + "unable to start requested SSL protected JMX connector"); + } + if (keyStorePassword == null) + { + throw new IllegalConfigurationException( "JVM system property 'javax.net.ssl.keyStorePassword' is not set, " + + "unable to start requested SSL protected JMX connector"); } - private static class NoLocalAddressSocket extends Socket + File ksf = new File(keyStorePath); + if (!ksf.exists()) { - @Override - public InetAddress getInetAddress() - { - return null; - } + throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf); + } + if (!ksf.canRead()) + { + throw new FileNotFoundException("Cannot read JMX management SSL keystore file: " + + ksf + ". Check permissions."); } } - + @Override public void registerObject(ManagedObject managedObject) throws JMException { _mbeanServer.registerMBean(managedObject, managedObject.getObjectName()); } + @Override public void unregisterObject(ManagedObject managedObject) throws JMException { _mbeanServer.unregisterMBean(managedObject.getObjectName()); } + @Override + public void close() + { + _log.debug("close() called"); + + closeConnectorAndRegistryServers(); + + unregisterAllMbeans(); + + CurrentActor.get().message(ManagementConsoleMessages.STOPPED(OPERATIONAL_LOGGING_NAME)); + } + + private void closeConnectorAndRegistryServers() + { + closeConnectorServer(); + closeRegistryServer(); + } + // checks if the system properties are set which enable the JVM's out-of-the-box JMXAgent. private boolean areOutOfTheBoxJMXOptionsSet() { @@ -433,29 +333,26 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry return false; } - //Stops the JMXConnectorServer and RMIRegistry, then unregisters any remaining MBeans from the MBeanServer - public void close() + private String getLocalhost() { - _log.debug("close() called"); - - if (_cs != null) + String localHost; + try { - // Stopping the JMX ConnectorServer - try - { - CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("JMX RMIConnectorServer", _cs.getAddress().getPort())); - _cs.stop(); - } - catch (IOException e) - { - _log.error("Exception while closing the JMX ConnectorServer: ", e); - } + localHost = InetAddress.getLocalHost().getHostName(); } - + catch(UnknownHostException ex) + { + localHost="127.0.0.1"; + } + return localHost; + } + + private void closeRegistryServer() + { if (_rmiRegistry != null) { // Stopping the RMI registry - CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer)); + CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _registryPort.getPort())); try { boolean success = UnicastRemoteObject.unexportObject(_rmiRegistry, false); @@ -468,8 +365,36 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry { _log.error("Exception while closing the RMI Registry: ", e); } + finally + { + _rmiRegistry = null; + } + } + } + + private void closeConnectorServer() + { + if (_cs != null) + { + // Stopping the JMX ConnectorServer + try + { + CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("JMX RMIConnectorServer", _cs.getAddress().getPort())); + _cs.stop(); + } + catch (IOException e) + { + _log.error("Exception while closing the JMX ConnectorServer: ", e); + } + finally + { + _cs = null; + } } - + } + + private void unregisterAllMbeans() + { //ObjectName query to gather all Qpid related MBeans ObjectName mbeanNameQuery = null; try @@ -492,8 +417,6 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry _log.error("Exception unregistering MBean '"+ name +"': " + e.getMessage()); } } - - CurrentActor.get().message(ManagementConsoleMessages.STOPPED()); } } diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java new file mode 100644 index 0000000000..8f087ba50c --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagement.java @@ -0,0 +1,343 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.jmx; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.UUID; + +import javax.management.JMException; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBean; +import org.apache.qpid.server.jmx.mbeans.UserManagementMBean; +import org.apache.qpid.server.jmx.mbeans.ServerInformationMBean; +import org.apache.qpid.server.jmx.mbeans.Shutdown; +import org.apache.qpid.server.jmx.mbeans.VirtualHostMBean; +import org.apache.qpid.server.logging.log4j.LoggingManagementFacade; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfigurationChangeListener; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.adapter.AbstractPluginAdapter; +import org.apache.qpid.server.plugin.PluginFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; +import org.apache.qpid.server.util.MapValueConverter; + +public class JMXManagement extends AbstractPluginAdapter implements ConfigurationChangeListener +{ + private static final Logger LOGGER = Logger.getLogger(JMXManagement.class); + + public static final String PLUGIN_TYPE = "MANAGEMENT-JMX"; + + // attributes + public static final String USE_PLATFORM_MBEAN_SERVER = "usePlatformMBeanServer"; + public static final String NAME = "name"; + + // default values + public static final String DEFAULT_NAME = "JMXManagement"; + public static final boolean DEFAULT_USE_PLATFORM_MBEAN_SERVER = true; + + @SuppressWarnings("serial") + private static final Collection AVAILABLE_ATTRIBUTES = Collections.unmodifiableCollection(new HashSet(Plugin.AVAILABLE_ATTRIBUTES){{ + add(NAME); + add(USE_PLATFORM_MBEAN_SERVER); + add(PluginFactory.PLUGIN_TYPE); + }}); + + @SuppressWarnings("serial") + private static final Map DEFAULTS = new HashMap(){{ + put(USE_PLATFORM_MBEAN_SERVER, DEFAULT_USE_PLATFORM_MBEAN_SERVER); + put(NAME, DEFAULT_NAME); + put(PluginFactory.PLUGIN_TYPE, PLUGIN_TYPE); + }}; + + @SuppressWarnings("serial") + private static final Map> ATTRIBUTE_TYPES = new HashMap>(){{ + put(USE_PLATFORM_MBEAN_SERVER, Boolean.class); + put(NAME, String.class); + put(PluginFactory.PLUGIN_TYPE, String.class); + }}; + + private final Broker _broker; + private JMXManagedObjectRegistry _objectRegistry; + + private final Map _children = new HashMap(); + + public JMXManagement(UUID id, Broker broker, Map attributes) + { + super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), broker.getTaskExecutor()); + _broker = broker; + addParent(Broker.class, broker); + } + + @Override + protected boolean setState(State currentState, State desiredState) + { + if(desiredState == State.ACTIVE) + { + try + { + start(); + } + catch (JMException e) + { + throw new RuntimeException("Couldn't start JMX management", e); + } + catch (IOException e) + { + throw new RuntimeException("Couldn't start JMX management", e); + } + return true; + } + else if(desiredState == State.STOPPED) + { + stop(); + return true; + } + return false; + } + + private void start() throws JMException, IOException + { + Port connectorPort = null; + Port registryPort = null; + Collection ports = _broker.getPorts(); + for (Port port : ports) + { + if (State.QUIESCED.equals(port.getActualState())) + { + continue; + } + + if(isRegistryPort(port)) + { + registryPort = port; + } + else if(isConnectorPort(port)) + { + connectorPort = port; + } + } + if(connectorPort == null) + { + throw new IllegalStateException("No JMX connector port found supporting protocol " + Protocol.JMX_RMI); + } + if(registryPort == null) + { + throw new IllegalStateException("No JMX RMI port found supporting protocol " + Protocol.RMI); + } + + _objectRegistry = new JMXManagedObjectRegistry(_broker, connectorPort, registryPort, this); + + _broker.addChangeListener(this); + + synchronized (_children) + { + for(VirtualHost virtualHost : _broker.getVirtualHosts()) + { + if(!_children.containsKey(virtualHost)) + { + LOGGER.debug("Create MBean for virtual host:" + virtualHost.getName()); + VirtualHostMBean mbean = new VirtualHostMBean(virtualHost, _objectRegistry); + LOGGER.debug("Check for additional MBeans for virtual host:" + virtualHost.getName()); + createAdditionalMBeansFromProviders(virtualHost, mbean); + } + } + Collection authenticationProviders = _broker.getAuthenticationProviders(); + for (AuthenticationProvider authenticationProvider : authenticationProviders) + { + if(authenticationProvider instanceof PasswordCredentialManagingAuthenticationProvider) + { + UserManagementMBean mbean = new UserManagementMBean( + (PasswordCredentialManagingAuthenticationProvider) authenticationProvider, + _objectRegistry); + _children.put(authenticationProvider, mbean); + } + } + } + new Shutdown(_objectRegistry); + new ServerInformationMBean(_objectRegistry, _broker); + if (LoggingManagementFacade.getCurrentInstance() != null) + { + new LoggingManagementMBean(LoggingManagementFacade.getCurrentInstance(), _objectRegistry); + } + _objectRegistry.start(); + } + + private boolean isConnectorPort(Port port) + { + return port.getProtocols().contains(Protocol.JMX_RMI); + } + + private boolean isRegistryPort(Port port) + { + return port.getProtocols().contains(Protocol.RMI); + } + + private void stop() + { + synchronized (_children) + { + for(ConfiguredObject object : _children.keySet()) + { + AMQManagedObject mbean = _children.get(object); + if (mbean instanceof ConfigurationChangeListener) + { + object.removeChangeListener((ConfigurationChangeListener)mbean); + } + try + { + mbean.unregister(); + } + catch (JMException e) + { + LOGGER.error("Error unregistering mbean", e); + } + } + _children.clear(); + } + _broker.removeChangeListener(this); + _objectRegistry.close(); + } + + @Override + public void stateChanged(ConfiguredObject object, State oldState, State newState) + { + // no-op + } + + @Override + public void childAdded(ConfiguredObject object, ConfiguredObject child) + { + synchronized (_children) + { + try + { + AMQManagedObject mbean; + if(child instanceof VirtualHost) + { + VirtualHost vhostChild = (VirtualHost)child; + mbean = new VirtualHostMBean(vhostChild, _objectRegistry); + } + else if(child instanceof PasswordCredentialManagingAuthenticationProvider) + { + mbean = new UserManagementMBean((PasswordCredentialManagingAuthenticationProvider) child, _objectRegistry); + } + else + { + mbean = null; + } + + if (mbean != null) + { + createAdditionalMBeansFromProviders(child, mbean); + } + } + catch(JMException e) + { + LOGGER.error("Error creating mbean", e); + // TODO - Implement error reporting on mbean creation + } + } + } + + @Override + public void childRemoved(ConfiguredObject object, ConfiguredObject child) + { + // TODO - implement vhost removal (possibly just removing the instanceof check below) + + synchronized (_children) + { + if(child instanceof PasswordCredentialManagingAuthenticationProvider) + { + AMQManagedObject mbean = _children.remove(child); + if(mbean != null) + { + try + { + mbean.unregister(); + } + catch(JMException e) + { + LOGGER.error("Error creating mbean", e); + //TODO - report error on removing child MBean + } + } + } + + } + } + + @Override + public void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue) + { + // no-op + } + + private void createAdditionalMBeansFromProviders(ConfiguredObject child, AMQManagedObject mbean) throws JMException + { + _children.put(child, mbean); + + QpidServiceLoader qpidServiceLoader = new QpidServiceLoader(); + for (MBeanProvider provider : qpidServiceLoader.instancesOf(MBeanProvider.class)) + { + LOGGER.debug("Consulting mbean provider : " + provider + " for child : " + child); + if (provider.isChildManageableByMBean(child)) + { + LOGGER.debug("Provider will create mbean "); + provider.createMBean(child, mbean); + // TODO track the mbeans that have been created on behalf of a child in a map, then + // if the child is ever removed, destroy these beans too. + } + } + } + + /** Added for testing purposes */ + Broker getBroker() + { + return _broker; + } + + @Override + public String getName() + { + return (String)getAttribute(NAME); + } + + @Override + public Collection getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementFactory.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementFactory.java new file mode 100644 index 0000000000..c2186c372b --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementFactory.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.jmx; + +import java.util.Map; +import java.util.UUID; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.plugin.PluginFactory; + +public class JMXManagementFactory implements PluginFactory +{ + private static final Logger LOGGER = Logger.getLogger(JMXManagementFactory.class); + + @Override + public Plugin createInstance(UUID id, Map attributes, Broker broker) + { + if (JMXManagement.PLUGIN_TYPE.equals(attributes.get(PLUGIN_TYPE))) + { + return new JMXManagement(id, broker, attributes); + } + else + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Skipping registration of JMX plugin as JMX Management disabled in config."); + } + return null; + } + } +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java deleted file mode 100644 index 7a232d2584..0000000000 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXService.java +++ /dev/null @@ -1,193 +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.jmx; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.ServiceLoader; - -import javax.management.JMException; -import javax.management.StandardMBean; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBean; -import org.apache.qpid.server.jmx.mbeans.UserManagementMBean; -import org.apache.qpid.server.jmx.mbeans.ConfigurationManagementMBean; -import org.apache.qpid.server.jmx.mbeans.ServerInformationMBean; -import org.apache.qpid.server.jmx.mbeans.Shutdown; -import org.apache.qpid.server.jmx.mbeans.VirtualHostMBean; -import org.apache.qpid.server.logging.log4j.LoggingFacade; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfigurationChangeListener; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.registry.ApplicationRegistry; - - -public class JMXService implements ConfigurationChangeListener -{ - private static final ClassLoader BUNDLE_CLASSLOADER = JMXService.class.getClassLoader(); - - private static final Logger LOGGER = Logger.getLogger(JMXService.class); - - private final Broker _broker; - private final JMXManagedObjectRegistry _objectRegistry; - private final Shutdown _shutdown; - private final ServerInformationMBean _serverInfo; - private final ConfigurationManagementMBean _configManagement; - private final LoggingManagementMBean _loggingManagement; - - private final Map _children = new HashMap(); - - public JMXService() throws AMQException, JMException - { - _broker = ApplicationRegistry.getInstance().getBroker(); - _objectRegistry = new JMXManagedObjectRegistry(); - - _broker.addChangeListener(this); - synchronized (_children) - { - for(VirtualHost virtualHost : _broker.getVirtualHosts()) - { - if(!_children.containsKey(virtualHost)) - { - _children.put(virtualHost, new VirtualHostMBean(virtualHost, _objectRegistry)); - } - } - } - _shutdown = new Shutdown(_objectRegistry); - _serverInfo = new ServerInformationMBean(_objectRegistry, _broker); - _configManagement = new ConfigurationManagementMBean(_objectRegistry); - _loggingManagement = new LoggingManagementMBean(LoggingFacade.getCurrentInstance(), _objectRegistry); - } - - public void start() throws IOException, ConfigurationException - { - _objectRegistry.start(); - } - - public void close() - { - _broker.removeChangeListener(this); - - _objectRegistry.close(); - } - - public void stateChanged(ConfiguredObject object, State oldState, State newState) - { - - } - - public void childAdded(ConfiguredObject object, ConfiguredObject child) - { - synchronized (_children) - { - try - { - AMQManagedObject mbean; - if(child instanceof VirtualHost) - { - VirtualHost vhostChild = (VirtualHost)child; - mbean = new VirtualHostMBean(vhostChild, _objectRegistry); - } - else if(child instanceof PasswordCredentialManagingAuthenticationProvider) - { - mbean = new UserManagementMBean((PasswordCredentialManagingAuthenticationProvider) child, _objectRegistry); - } - else - { - mbean = null; - } - - if (mbean != null) - { - createAdditionalMBeansFromProviders(child, mbean); - } - } - catch(JMException e) - { - LOGGER.error("Error creating mbean", e); - // TODO - Implement error reporting on mbean creation - } - } - } - - - public void childRemoved(ConfiguredObject object, ConfiguredObject child) - { - // TODO - implement vhost removal (possibly just removing the instanceof check below) - - synchronized (_children) - { - if(child instanceof PasswordCredentialManagingAuthenticationProvider) - { - AMQManagedObject mbean = _children.remove(child); - if(mbean != null) - { - try - { - mbean.unregister(); - } - catch(JMException e) - { - LOGGER.error("Error creating mbean", e); - //TODO - report error on removing child MBean - } - } - } - - } - } - - private void createAdditionalMBeansFromProviders(ConfiguredObject child, AMQManagedObject mbean) throws JMException - { - _children.put(child, mbean); - - for (Iterator iterator = getMBeanProviderIterator(); iterator.hasNext();) - { - MBeanProvider provider = iterator.next(); - LOGGER.debug("Consulting mbean provider : " + provider + " for child : " + child); - if (provider.isChildManageableByMBean(child)) - { - LOGGER.debug("Provider will create mbean "); - StandardMBean bean = provider.createMBean(child, mbean); - // TODO track the mbeans that have been created on behalf of a child in a map, then - // if the child is ever removed, destroy these beans too. - } - } - } - - /** - * Finds all classes implementing the {@link MBeanProvider} interface. This will find - * only those classes which are visible to the classloader of this OSGI bundle. - */ - private Iterator getMBeanProviderIterator() - { - return ServiceLoader.load(MBeanProvider.class, BUNDLE_CLASSLOADER).iterator(); - } -} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java index a2a0d2d093..8bc2afb176 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java @@ -22,26 +22,22 @@ package org.apache.qpid.server.jmx; import org.apache.log4j.Logger; -import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.ManagementActor; -import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import javax.management.Attribute; import javax.management.JMException; import javax.management.MBeanInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanServer; -import javax.management.Notification; -import javax.management.NotificationListener; import javax.management.ObjectName; import javax.management.RuntimeErrorException; -import javax.management.remote.JMXConnectionNotification; -import javax.management.remote.JMXPrincipal; import javax.management.remote.MBeanServerForwarder; import javax.security.auth.Subject; import java.lang.reflect.InvocationHandler; @@ -51,27 +47,32 @@ import java.lang.reflect.Proxy; import java.security.AccessControlContext; import java.security.AccessController; import java.util.Arrays; -import java.util.Map; -import java.util.Set; /** * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. It delegates * JMX access decisions to the SecurityPlugin. */ -public class MBeanInvocationHandlerImpl implements InvocationHandler, NotificationListener +public class MBeanInvocationHandlerImpl implements InvocationHandler { private static final Logger _logger = Logger.getLogger(MBeanInvocationHandlerImpl.class); - private final IApplicationRegistry _appRegistry = ApplicationRegistry.getInstance(); private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate"; private MBeanServer _mbs; - private final ManagementActor _logActor = new ManagementActor(_appRegistry.getRootMessageLogger()); - private final boolean _managementRightsInferAllAccess = - _appRegistry.getConfiguration().getManagementRightsInferAllAccess(); + private final ManagementActor _logActor; - public static MBeanServerForwarder newProxyInstance() + private final boolean _managementRightsInferAllAccess; + private final Broker _broker; + + MBeanInvocationHandlerImpl(Broker broker) + { + _managementRightsInferAllAccess = Boolean.valueOf(System.getProperty(BrokerProperties.PROPERTY_MANAGEMENT_RIGHTS_INFER_ALL_ACCESS, "true")); + _broker = broker; + _logActor = new ManagementActor(broker.getRootMessageLogger()); + } + + public static MBeanServerForwarder newProxyInstance(Broker broker) { - final InvocationHandler handler = new MBeanInvocationHandlerImpl(); + final InvocationHandler handler = new MBeanInvocationHandlerImpl(broker); final Class[] interfaces = new Class[] { MBeanServerForwarder.class }; Object proxy = Proxy.newProxyInstance(MBeanServerForwarder.class.getClassLoader(), interfaces, handler); @@ -101,7 +102,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati { ObjectName mbean = (ObjectName) args[0]; - if(!DefaultManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain())) + if(!ManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain())) { return true; } @@ -151,11 +152,13 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati return method.invoke(_mbs, args); } - // Retrieve JMXPrincipal from Subject - Set principals = subject.getPrincipals(JMXPrincipal.class); - if (principals == null || principals.isEmpty()) + try + { + AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); + } + catch(Exception e) { - throw new SecurityException("Access denied: no JMX principal"); + throw new SecurityException("Access denied: no authenticated principal", e); } // Save the subject @@ -211,11 +214,16 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati SecurityManager security; if (vhost == null) { - security = _appRegistry.getSecurityManager(); + security = _broker.getSecurityManager(); } else { - security = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager(); + VirtualHost virtualHost = _broker.findVirtualHostByName(vhost); + if (virtualHost == null) + { + throw new IllegalArgumentException("Virtual host with name '" + vhost + "' is not found."); + } + security = virtualHost.getSecurityManager(); } methodName = getMethodName(method, args); @@ -360,50 +368,5 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati return (methodName.startsWith("query") || methodName.startsWith("get") || methodName.startsWith("is")); } - /** - * Receives notifications from the MBeanServer. - */ - public void handleNotification(final Notification notification, final Object handback) - { - assert notification instanceof JMXConnectionNotification; - - final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); - final String type = notification.getType(); - - if (_logger.isDebugEnabled()) - { - _logger.debug("Notification connectionId : " + connectionId + " type : " + type - + " Notification handback : " + handback); - } - - // Normally JMXManagedObjectRegistry provides a Map as handback data containing a map - // between connection id and username. - String user = null; - if (handback instanceof Map) - { - final Map connectionIdUsernameMap = (Map) handback; - user = connectionIdUsernameMap.get(connectionId); - } - - // If user is still null, fallback to an unordered list of Principals from the connection id. - if (user == null) - { - final String[] splitConnectionId = connectionId.split(" "); - user = splitConnectionId[1]; - } - - // use a separate instance of actor as subject is not set on connect/disconnect - // we need to pass principal name explicitly into log actor - LogActor logActor = new ManagementActor(_appRegistry.getRootMessageLogger(), user); - if (JMXConnectionNotification.OPENED.equals(type)) - { - logActor.message(ManagementConsoleMessages.OPEN(user)); - } - else if (JMXConnectionNotification.CLOSED.equals(type) || - JMXConnectionNotification.FAILED.equals(type)) - { - logActor.message(ManagementConsoleMessages.CLOSE(user)); - } - } } diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java index 83909dbe72..b80ddc7fac 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java @@ -21,17 +21,16 @@ package org.apache.qpid.server.jmx; -import java.util.ServiceLoader; - import javax.management.JMException; import javax.management.StandardMBean; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.plugin.QpidServiceLoader; /** * A provider of an mbean implementation. * - * Provider implementations are advertised as services and loaded via {@link ServiceLoader}. + * Provider implementations are advertised as services and loaded by a {@link QpidServiceLoader}. */ public interface MBeanProvider { diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java new file mode 100644 index 0000000000..ae0574dc21 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporter.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx; + +import static javax.management.remote.JMXConnectionNotification.CLOSED; +import static javax.management.remote.JMXConnectionNotification.FAILED; +import static javax.management.remote.JMXConnectionNotification.OPENED; + +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.remote.JMXConnectionNotification; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.ManagementActor; +import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; + +public class ManagementLogonLogoffReporter implements NotificationListener, NotificationFilter +{ + private static final Logger LOGGER = Logger.getLogger(ManagementLogonLogoffReporter.class); + private final RootMessageLogger _rootMessageLogger; + private final UsernameAccessor _usernameAccessor; + + public ManagementLogonLogoffReporter(RootMessageLogger rootMessageLogger, UsernameAccessor usernameAccessor) + { + _rootMessageLogger = rootMessageLogger; + _usernameAccessor = usernameAccessor; + } + + @Override + public void handleNotification(final Notification notification, final Object handback) + { + final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); + final String type = notification.getType(); + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Notification connectionId : " + connectionId + " type : " + type); + } + + String user = _usernameAccessor.getUsernameForConnectionId(connectionId); + + // If user is still null, fallback to an unordered list of Principals from the connection id. + if (user == null) + { + final String[] splitConnectionId = connectionId.split(" "); + user = splitConnectionId[1]; + } + + // use a separate instance of actor as subject is not set on connect/disconnect + // we need to pass principal name explicitly into log actor + LogActor logActor = new ManagementActor(_rootMessageLogger, user); + if (JMXConnectionNotification.OPENED.equals(type)) + { + logActor.message(ManagementConsoleMessages.OPEN(user)); + } + else if (JMXConnectionNotification.CLOSED.equals(type) || + JMXConnectionNotification.FAILED.equals(type)) + { + logActor.message(ManagementConsoleMessages.CLOSE(user)); + } + } + + @Override + public boolean isNotificationEnabled(Notification notification) + { + return notification instanceof JMXConnectionNotification && isLogonTypeEvent(notification); + } + + private boolean isLogonTypeEvent(Notification notification) + { + final String type = notification.getType(); + return CLOSED.equals(type) || FAILED.equals(type) || OPENED.equals(type); + } + +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java new file mode 100644 index 0000000000..0cbb0d2687 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameAccessor.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx; + +public interface UsernameAccessor +{ + public String getUsernameForConnectionId(String connectionId); + +} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java new file mode 100644 index 0000000000..838e9e5664 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/UsernameCachingRMIJRMPServer.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx; + +import static javax.management.remote.JMXConnectionNotification.CLOSED; +import static javax.management.remote.JMXConnectionNotification.FAILED; + +import java.io.IOException; +import java.rmi.server.RMIClientSocketFactory; +import java.rmi.server.RMIServerSocketFactory; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.remote.JMXConnectionNotification; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.rmi.RMIConnection; +import javax.management.remote.rmi.RMIJRMPServerImpl; +import javax.security.auth.Subject; + +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; + +/** + * An implementation of RMIJRMPServerImpl that caches the usernames of users as they log-on + * and makes the same available via {@link UsernameAccessor#getUsernameForConnectionId(String)}. + * + * Caller is responsible for installing this object as a {@link NotificationListener} of the + * {@link JMXConnectorServer} so the cache entries are removed as the clients disconnect. + * + */ +public class UsernameCachingRMIJRMPServer extends RMIJRMPServerImpl implements NotificationListener, NotificationFilter, UsernameAccessor +{ + // ConnectionId is guaranteed to be unique per client connection, according to the JMX spec. + private final Map _connectionIdUsernameMap = new ConcurrentHashMap(); + + UsernameCachingRMIJRMPServer(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf, + Map env) throws IOException + { + super(port, csf, ssf, env); + } + + @Override + protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException + { + final RMIConnection makeClient = super.makeClient(connectionId, subject); + final AuthenticatedPrincipal authenticatedPrincipalFromSubject = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); + _connectionIdUsernameMap.put(connectionId, authenticatedPrincipalFromSubject.getName()); + return makeClient; + } + + @Override + public String getUsernameForConnectionId(String connectionId) + { + return _connectionIdUsernameMap.get(connectionId); + } + + @Override + public void handleNotification(Notification notification, Object handback) + { + final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); + removeConnectionIdFromCache(connectionId); + } + + @Override + public boolean isNotificationEnabled(Notification notification) + { + return isClientDisconnectEvent(notification); + } + + private void removeConnectionIdFromCache(String connectionId) + { + _connectionIdUsernameMap.remove(connectionId); + } + + private boolean isClientDisconnectEvent(Notification notification) + { + final String type = notification.getType(); + return CLOSED.equals(type) || FAILED.equals(type); + } + +} \ No newline at end of file diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java deleted file mode 100644 index beffb4eaa9..0000000000 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConfigurationManagementMBean.java +++ /dev/null @@ -1,56 +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.jmx.mbeans; - -import org.apache.qpid.management.common.mbeans.ConfigurationManagement; -import org.apache.qpid.server.jmx.AMQManagedObject; -import org.apache.qpid.server.jmx.ManagedObject; -import org.apache.qpid.server.jmx.ManagedObjectRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; - -import javax.management.JMException; -import javax.management.NotCompliantMBeanException; - -public class ConfigurationManagementMBean extends AMQManagedObject implements ConfigurationManagement -{ - - public ConfigurationManagementMBean(ManagedObjectRegistry registry) throws JMException - { - super(ConfigurationManagement.class, ConfigurationManagement.TYPE, registry); - register(); - } - - public String getObjectInstanceName() - { - return ConfigurationManagement.TYPE; - } - - public void reloadSecurityConfiguration() throws Exception - { - ApplicationRegistry.getInstance().getConfiguration().reparseConfigFileSecuritySections(); - } - - @Override - public ManagedObject getParentObject() - { - return null; - } -} diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java index 0dac8ebe37..d6f4b5d8c9 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBean.java @@ -26,7 +26,7 @@ import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; import org.apache.qpid.server.jmx.AMQManagedObject; import org.apache.qpid.server.jmx.ManagedObject; import org.apache.qpid.server.jmx.ManagedObjectRegistry; -import org.apache.qpid.server.logging.log4j.LoggingFacade; +import org.apache.qpid.server.logging.log4j.LoggingManagementFacade; import org.apache.qpid.server.logging.log4j.LoggingFacadeException; import javax.management.JMException; @@ -55,7 +55,8 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM private static final TabularType LOGGER_LEVEL_TABULAR_TYE; private static final CompositeType LOGGER_LEVEL_COMPOSITE_TYPE; - private final LoggingFacade _configurator; + private final LoggingManagementFacade _loggingManagementFacade; + private final String[] _allAvailableLogLevels; static { @@ -77,12 +78,13 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM throw new ExceptionInInitializerError(e); } } - - public LoggingManagementMBean(LoggingFacade configurator, ManagedObjectRegistry registry) throws JMException + + public LoggingManagementMBean(LoggingManagementFacade loggingManagementFacade, ManagedObjectRegistry registry) throws JMException { super(LoggingManagement.class, LoggingManagement.TYPE, registry); register(); - _configurator = configurator; + _loggingManagementFacade = loggingManagementFacade; + _allAvailableLogLevels = buildAllAvailableLoggerLevelsWithInheritedPsuedoLogLevel(_loggingManagementFacade); } @Override @@ -100,30 +102,26 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM @Override public Integer getLog4jLogWatchInterval() { - return _configurator.getLog4jLogWatchInterval(); + return _loggingManagementFacade.getLog4jLogWatchInterval(); } @Override public String[] getAvailableLoggerLevels() { - List levels = _configurator.getAvailableLoggerLevels(); - List mbeanLevels = new ArrayList(levels); - mbeanLevels.add(INHERITED_PSUEDO_LOG_LEVEL); - - return mbeanLevels.toArray(new String[mbeanLevels.size()]); + return _allAvailableLogLevels; } @Override public TabularData viewEffectiveRuntimeLoggerLevels() { - Map levels = _configurator.retrieveRuntimeLoggersLevels(); + Map levels = _loggingManagementFacade.retrieveRuntimeLoggersLevels(); return createTabularDataFromLevelsMap(levels); } @Override public String getRuntimeRootLoggerLevel() { - return _configurator.retrieveRuntimeRootLoggerLevel(); + return _loggingManagementFacade.retrieveRuntimeRootLoggerLevel(); } @Override @@ -139,7 +137,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM return false; } - _configurator.setRuntimeRootLoggerLevel(level); + _loggingManagementFacade.setRuntimeRootLoggerLevel(level); return true; } @@ -159,7 +157,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM try { - _configurator.setRuntimeLoggerLevel(logger, validatedLevel); + _loggingManagementFacade.setRuntimeLoggerLevel(logger, validatedLevel); } catch (LoggingFacadeException e) { @@ -175,7 +173,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM Map levels; try { - levels = _configurator.retrieveConfigFileLoggersLevels(); + levels = _loggingManagementFacade.retrieveConfigFileLoggersLevels(); } catch (LoggingFacadeException e) { @@ -191,7 +189,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM { try { - return _configurator.retrieveConfigFileRootLoggerLevel().toUpperCase(); + return _loggingManagementFacade.retrieveConfigFileRootLoggerLevel().toUpperCase(); } catch (LoggingFacadeException e) { @@ -216,7 +214,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM try { - _configurator.setConfigFileLoggerLevel(logger, validatedLevel); + _loggingManagementFacade.setConfigFileLoggerLevel(logger, validatedLevel); } catch (LoggingFacadeException e) { @@ -241,7 +239,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM try { - _configurator.setConfigFileRootLoggerLevel(level); + _loggingManagementFacade.setConfigFileRootLoggerLevel(level); return true; } catch (LoggingFacadeException e) @@ -257,7 +255,7 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM try { - _configurator.reload(); + _loggingManagementFacade.reload(); } catch (LoggingFacadeException e) { @@ -283,9 +281,8 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM private void validateLevelNotAllowingInherited(String level) { - final List availableLoggerLevels = _configurator.getAvailableLoggerLevels(); - if (!availableLoggerLevels.contains(level) - && !availableLoggerLevels.contains(String.valueOf(level).toUpperCase())) + final List availableLoggerLevels = _loggingManagementFacade.getAvailableLoggerLevels(); + if (level == null || !availableLoggerLevels.contains(level.toUpperCase())) { throw new IllegalArgumentException(level + " not known"); } @@ -305,7 +302,6 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM return loggerLevelList; } - private CompositeData createRow(String loggerName, String level) { Object[] itemData = {loggerName, level.toUpperCase()}; @@ -321,4 +317,13 @@ public class LoggingManagementMBean extends AMQManagedObject implements LoggingM throw new RuntimeException(ode); } } + + private String[] buildAllAvailableLoggerLevelsWithInheritedPsuedoLogLevel(LoggingManagementFacade loggingManagementFacade) + { + List levels = loggingManagementFacade.getAvailableLoggerLevels(); + List mbeanLevels = new ArrayList(levels); + mbeanLevels.add(INHERITED_PSUEDO_LOG_LEVEL); + + return mbeanLevels.toArray(new String[mbeanLevels.size()]); + } } diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java index 5c8b0f7194..94fac218ff 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java @@ -513,7 +513,6 @@ public class QueueMBean extends AMQManagedObject implements ManagedQueue, QueueN { _queue.visit(new QueueEntryVisitor() { - public boolean visit(final QueueEntry entry) { final ServerMessage message = entry.getMessage(); @@ -525,11 +524,9 @@ public class QueueMBean extends AMQManagedObject implements ManagedQueue, QueueN && (messageId <= toMessageId)) { txn.dequeue(entry); - return true; } - return false; } - return true; + return false; } }); } diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java index 6990a40dee..51dea92775 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostMBean.java @@ -65,7 +65,7 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual _managerMBean = new VirtualHostManagerMBean(this); } - private void initQueues() throws JMException + private void initQueues() { synchronized (_children) { @@ -73,13 +73,20 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual { if(!_children.containsKey(queue)) { - _children.put(queue, new QueueMBean(queue, this)); + try + { + _children.put(queue, new QueueMBean(queue, this)); + } + catch(Exception e) + { + LOGGER.error("Cannot create queue mbean for queue " + queue.getName(), e); + } } } } } - private void initExchanges() throws JMException + private void initExchanges() { synchronized (_children) { @@ -87,13 +94,20 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual { if(!_children.containsKey(exchange)) { - _children.put(exchange, new ExchangeMBean(exchange, this)); + try + { + _children.put(exchange, new ExchangeMBean(exchange, this)); + } + catch(Exception e) + { + LOGGER.error("Cannot create exchange mbean for exchange " + exchange.getName(), e); + } } } } } - private void initConnections() throws JMException + private void initConnections() { synchronized (_children) { @@ -101,7 +115,14 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual { if(!_children.containsKey(conn)) { - _children.put(conn, new ConnectionMBean(conn, this)); + try + { + _children.put(conn, new ConnectionMBean(conn, this)); + } + catch(Exception e) + { + LOGGER.error("Cannot create connection mbean for connection " + conn.getName(), e); + } } } } @@ -119,7 +140,7 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual public void stateChanged(ConfiguredObject object, State oldState, State newState) { - // ignore + // no-op } public void childAdded(ConfiguredObject object, ConfiguredObject child) @@ -208,4 +229,35 @@ public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtual return queues; } + + @Override + public void unregister() throws JMException + { + synchronized (_children) + { + for (AMQManagedObject mbean : _children.values()) + { + if(mbean != null) + { + try + { + mbean.unregister(); + } + catch(JMException e) + { + LOGGER.error("Failed to remove mbean for child : " + mbean, e); + } + } + } + _children.clear(); + } + _managerMBean.unregister(); + } + + @Override + public void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue) + { + // no-op + } + } diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java index b3dbbc424a..67ac1bdc7c 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java @@ -229,10 +229,9 @@ public class VirtualHostManagerMBean extends AbstractStatisticsGatheringMBean _attributes = new HashMap(); + private final Broker _broker = mock(Broker.class); + private UUID _id = UUID.randomUUID(); + + public void testJMXConfigured() throws Exception + { + _attributes.put(PluginFactory.PLUGIN_TYPE, JMXManagement.PLUGIN_TYPE); + + JMXManagement jmxManagement = (JMXManagement) _jmxManagementFactory.createInstance(_id, _attributes, _broker); + + assertNotNull(jmxManagement); + assertEquals("Unexpected plugin type", JMXManagement.PLUGIN_TYPE, jmxManagement.getAttribute(JMXManagementFactory.PLUGIN_TYPE)); + assertEquals("Unexpected default mbean platform", JMXManagement.DEFAULT_USE_PLATFORM_MBEAN_SERVER, jmxManagement.getAttribute(JMXManagement.USE_PLATFORM_MBEAN_SERVER)); + assertEquals("Unexpected default name", JMXManagement.DEFAULT_NAME, jmxManagement.getAttribute(JMXManagement.NAME)); + } + + public void testCreateInstanceReturnsNullWhenPluginTypeMissing() + { + assertNull(_jmxManagementFactory.createInstance(_id, _attributes, _broker)); + } + + public void testCreateInstanceReturnsNullWhenPluginTypeNotJmx() + { + _attributes.put(PluginFactory.PLUGIN_TYPE, "notJmx"); + assertNull(_jmxManagementFactory.createInstance(_id, _attributes, _broker)); + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java deleted file mode 100644 index c1df9afc5d..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogActorTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.jmx; - -import java.util.HashMap; -import java.util.Map; - -import javax.management.JMException; -import javax.management.MBeanServerConnection; -import javax.management.ObjectName; -import javax.management.remote.JMXConnector; -import javax.management.remote.JMXConnectorFactory; -import javax.management.remote.JMXServiceURL; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.SecurityPlugin; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; -import org.apache.qpid.server.util.TestApplicationRegistry; -import org.apache.qpid.test.utils.QpidTestCase; - -public class ManagementLogActorTest extends QpidTestCase -{ - private ApplicationRegistry _registry; - private JMXManagedObjectRegistry _objectRegistry; - private int _registryPort; - private int _connectorPort; - private TestPlugin _plugin; - - @Override - public void setUp() throws Exception - { - super.setUp(); - - _registryPort = findFreePort(); - _connectorPort = getNextAvailable(_registryPort + 1); - XMLConfiguration config = new XMLConfiguration(); - config.addProperty(ServerConfiguration.MGMT_JMXPORT_REGISTRYSERVER, _registryPort + ""); - config.addProperty(ServerConfiguration.MGMT_JMXPORT_CONNECTORSERVER, _connectorPort + ""); - _registry = new TestApplicationRegistry(new ServerConfiguration(config)); - ApplicationRegistry.initialise(_registry); - - _plugin = new TestPlugin(); - _registry.getSecurityManager().addHostPlugin(_plugin); - - _objectRegistry = new JMXManagedObjectRegistry(); - new TestMBean(_objectRegistry); - _objectRegistry.start(); - } - - public void tearDown() throws Exception - { - _objectRegistry.close(); - ApplicationRegistry.remove(); - super.tearDown(); - } - - public void testPrincipalInLogMessage() throws Throwable - { - Map environment = new HashMap(); - environment.put(JMXConnector.CREDENTIALS, new String[] { "admin", "admin" }); - String urlString = "service:jmx:rmi:///jndi/rmi://localhost:" + _registryPort + "/jmxrmi"; - JMXServiceURL url = new JMXServiceURL(urlString); - JMXConnector jmxConnector = JMXConnectorFactory.connect(url, environment); - MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection(); - ObjectName mbeanObject = new ObjectName("org.apache.qpid:type=TestMBean,name=test"); - - String actorLogMessage = (String) mbsc.getAttribute(mbeanObject, "ActorLogMessage"); - - assertTrue("Unexpected log principal in security plugin", _plugin.getLogMessage().startsWith("[mng:admin")); - assertTrue("Unexpected log principal in MBean", actorLogMessage.startsWith("[mng:admin")); - } - - public static class TestMBean extends DefaultManagedObject implements CurrentActorRetriever - { - - public TestMBean(ManagedObjectRegistry registry) throws JMException - { - super(CurrentActorRetriever.class, "TestMBean", registry); - register(); - } - - @Override - public String getObjectInstanceName() - { - return "test"; - } - - @Override - public ManagedObject getParentObject() - { - return null; - } - - @Override - public String getActorLogMessage() - { - return CurrentActor.get().getLogMessage(); - } - - } - - public static interface CurrentActorRetriever - { - String getActorLogMessage(); - } - - public static class TestPlugin implements SecurityPlugin - { - private String _logMessage; - - @Override - public void configure(ConfigurationPlugin config) throws ConfigurationException - { - } - - @Override - public Result getDefault() - { - return Result.ALLOWED; - } - - @Override - public Result access(ObjectType objectType, Object instance) - { - return Result.ALLOWED; - } - - @Override - public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) - { - // set thread name to work around logic in MangementActor - Thread.currentThread().setName("RMI TCP Connection(1)-" + System.currentTimeMillis()); - _logMessage = CurrentActor.get().getLogMessage(); - return Result.ALLOWED; - } - - public String getLogMessage() - { - return _logMessage; - } - - } - -} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java new file mode 100644 index 0000000000..ba9c2cdaa5 --- /dev/null +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/ManagementLogonLogoffReporterTest.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.jmx; + +import static javax.management.remote.JMXConnectionNotification.OPENED; +import static javax.management.remote.JMXConnectionNotification.CLOSED; +import static javax.management.remote.JMXConnectionNotification.FAILED; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; + +import javax.management.remote.JMXConnectionNotification; + +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.RootMessageLogger; + +import junit.framework.TestCase; + +public class ManagementLogonLogoffReporterTest extends TestCase +{ + private static final String TEST_JMX_UNIQUE_CONNECTION_ID = "jmxconnectionid1 jmxuser,group"; + private static final String TEST_USER = "jmxuser"; + + private ManagementLogonLogoffReporter _reporter; + private UsernameAccessor _usernameAccessor; + private RootMessageLogger _rootMessageLogger; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _usernameAccessor = mock(UsernameAccessor.class); + _rootMessageLogger = mock(RootMessageLogger.class); + // Enable messaging so we can valid the generated strings + when(_rootMessageLogger.isMessageEnabled(any(LogActor.class), anyString())).thenReturn(true); + + _reporter = new ManagementLogonLogoffReporter(_rootMessageLogger, _usernameAccessor); + } + + public void testOpenedNotification() + { + when(_usernameAccessor.getUsernameForConnectionId(TEST_JMX_UNIQUE_CONNECTION_ID)).thenReturn(TEST_USER); + JMXConnectionNotification openNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, OPENED); + + _reporter.handleNotification(openNotification, null); + + verify(_rootMessageLogger).rawMessage("[main] MNG-1007 : Open : User jmxuser", "qpid.message.managementconsole.open"); + } + + public void testClosedNotification() + { + when(_usernameAccessor.getUsernameForConnectionId(TEST_JMX_UNIQUE_CONNECTION_ID)).thenReturn(TEST_USER); + JMXConnectionNotification closeNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, CLOSED); + + _reporter.handleNotification(closeNotification, null); + + verify(_rootMessageLogger).rawMessage("[main] MNG-1008 : Close : User jmxuser", "qpid.message.managementconsole.close"); + } + + public void tesNotifiedForLogOnTypeEvents() + { + JMXConnectionNotification openNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, OPENED); + JMXConnectionNotification closeNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, CLOSED); + JMXConnectionNotification failedNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, FAILED); + + assertTrue(_reporter.isNotificationEnabled(openNotification)); + assertTrue(_reporter.isNotificationEnabled(closeNotification)); + assertTrue(_reporter.isNotificationEnabled(failedNotification)); + + JMXConnectionNotification otherNotification = createMockNotification(TEST_JMX_UNIQUE_CONNECTION_ID, "other"); + assertFalse(_reporter.isNotificationEnabled(otherNotification)); + } + + private JMXConnectionNotification createMockNotification(String connectionId, String notificationType) + { + JMXConnectionNotification notification = mock(JMXConnectionNotification.class); + when(notification.getConnectionId()).thenReturn(connectionId); + when(notification.getType()).thenReturn(notificationType); + return notification; + } +} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java index ae1be5db00..0f33e78d03 100644 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java +++ b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/LoggingManagementMBeanTest.java @@ -39,7 +39,7 @@ import junit.framework.TestCase; import org.apache.qpid.management.common.mbeans.LoggingManagement; import org.apache.qpid.server.jmx.ManagedObjectRegistry; -import org.apache.qpid.server.logging.log4j.LoggingFacade; +import org.apache.qpid.server.logging.log4j.LoggingManagementFacade; public class LoggingManagementMBeanTest extends TestCase { @@ -47,13 +47,13 @@ public class LoggingManagementMBeanTest extends TestCase private static final String TEST_LEVEL2 = "LEVEL2"; private LoggingManagementMBean _loggingMBean; - private LoggingFacade _mockLoggingFacade; + private LoggingManagementFacade _mockLoggingFacade; private ManagedObjectRegistry _mockManagedObjectRegistry; @Override protected void setUp() throws Exception { - _mockLoggingFacade = mock(LoggingFacade.class); + _mockLoggingFacade = mock(LoggingManagementFacade.class); final List listOfLevels = new ArrayList() {{ add(TEST_LEVEL1); diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java deleted file mode 100644 index 7473a4d3e7..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java +++ /dev/null @@ -1,124 +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.systest.management.jmx; - -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedExchange; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -/** - * Tests the JMX API for the Managed Broker. - * - */ -public class BrokerManagementTest extends QpidBrokerTestCase -{ - private static final String VIRTUAL_HOST = "test"; - - /** - * JMX helper. - */ - private JMXTestUtils _jmxUtils; - private ManagedBroker _managedBroker; - - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - super.setUp(); - _jmxUtils.open(); - _managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); - } - - public void tearDown() throws Exception - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - super.tearDown(); - } - - /** - * Tests queue creation/deletion also verifying the automatic binding to the default exchange. - */ - public void testCreateQueueAndDeletion() throws Exception - { - final String queueName = getTestQueueName(); - final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString()); - - // Check that bind does not exist before queue creation - assertFalse("Binding to " + queueName + " should not exist in default exchange before queue creation", - defaultExchange.bindings().containsKey(new String[] {queueName})); - - _managedBroker.createNewQueue(queueName, "testowner", true); - - // Ensure the queue exists - assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName)); - assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName)); - - // Now verify that the default exchange has been bound. - assertTrue("Binding to " + queueName + " should exist in default exchange after queue creation", - defaultExchange.bindings().containsKey(new String[] {queueName})); - - // Now delete the queue - _managedBroker.deleteQueue(queueName); - - // Finally ensure that the binding has been removed. - assertFalse("Binding to " + queueName + " should not exist in default exchange after queue deletion", - defaultExchange.bindings().containsKey(new String[] {queueName})); - } - - /** - * Tests exchange creation/deletion via JMX API. - */ - public void testCreateExchangeAndUnregister() throws Exception - { - String exchangeName = getTestName(); - _managedBroker.createNewExchange(exchangeName, "topic", true); - - ManagedExchange exchange = _jmxUtils.getManagedExchange(exchangeName); - assertNotNull("Exchange should exist", exchange); - - _managedBroker.unregisterExchange(exchangeName); - } - - /** - * Tests that it is disallowed to unregister the default exchange. - */ - public void testUnregisterOfDefaultExchangeDisallowed() throws Exception - { - String defaultExchangeName = ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString(); - - try - { - _managedBroker.unregisterExchange(defaultExchangeName); - fail("Exception not thrown"); - } - catch (UnsupportedOperationException e) - { - // PASS - assertEquals("'<>' is a reserved exchange and can't be deleted", e.getMessage()); - } - final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName); - assertNotNull("Exchange should exist", defaultExchange); - } - -} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java deleted file mode 100644 index 28d7bf4aed..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java +++ /dev/null @@ -1,283 +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.systest.management.jmx; - -import java.io.IOException; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.TabularData; - -import org.apache.commons.lang.StringUtils; -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.management.common.mbeans.ManagedConnection; -import org.apache.qpid.management.common.mbeans.ManagedQueue; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -public class ConnectionManagementTest extends QpidBrokerTestCase -{ - private static final String VIRTUAL_HOST_NAME = "test"; - - private JMXTestUtils _jmxUtils; - private Connection _connection; - - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); // modifies broker config therefore must be done before super.setUp() - super.setUp(); - _jmxUtils.open(); - } - - public void tearDown() throws Exception - { - try - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - } - finally - { - super.tearDown(); - } - } - - public void testNumberOfManagedConnectionsMatchesNumberOfClientConnections() throws Exception - { - assertEquals("Expected no managed connections", 0, getManagedConnections().size()); - - _connection = getConnection(); - assertEquals("Expected one managed connection", 1, getManagedConnections().size()); - - _connection.close(); - assertEquals("Expected no managed connections after client connection closed", 0, getManagedConnections().size()); - } - - public void testGetAttributes() throws Exception - { - _connection = getConnection(); - final ManagedConnection mBean = getConnectionMBean(); - - checkAuthorisedId(mBean); - checkClientVersion(mBean); - checkClientId(mBean); - } - - public void testNonTransactedSession() throws Exception - { - _connection = getConnection(); - - boolean transactional = false; - boolean flowBlocked = false; - - _connection.createSession(transactional, Session.AUTO_ACKNOWLEDGE); - - final ManagedConnection mBean = getConnectionMBean(); - final CompositeDataSupport row = getTheOneChannelRow(mBean); - assertChannelRowData(row, 0, transactional, flowBlocked); - } - - public void testTransactedSessionWithUnackMessages() throws Exception - { - _connection = getConnection(); - _connection.start(); - - boolean transactional = true; - int numberOfMessages = 2; - final Session session = _connection.createSession(transactional, Session.SESSION_TRANSACTED); - final Destination destination = session.createQueue(getTestQueueName()); - final MessageConsumer consumer = session.createConsumer(destination); - - sendMessage(session, destination, numberOfMessages); - receiveMessagesWithoutCommit(consumer, numberOfMessages); - - final ManagedConnection mBean = getConnectionMBean(); - final CompositeDataSupport row = getTheOneChannelRow(mBean); - boolean flowBlocked = false; - assertChannelRowData(row, numberOfMessages, transactional, flowBlocked); - - // check that commit advances the lastIoTime - final Date initialLastIOTime = mBean.getLastIoTime(); - session.commit(); - assertTrue("commit should have caused last IO time to advance", mBean.getLastIoTime().after(initialLastIOTime)); - - // check that channels() now returns one session with no unacknowledged messages - final CompositeDataSupport rowAfterCommit = getTheOneChannelRow(mBean); - final Number unackCountAfterCommit = (Number) rowAfterCommit.get(ManagedConnection.UNACKED_COUNT); - assertEquals("Unexpected number of unacknowledged messages", 0, unackCountAfterCommit); - } - - - public void testProducerFlowBlocked() throws Exception - { - _connection = getConnection(); - _connection.start(); - - String queueName = getTestQueueName(); - Session session = _connection.createSession(true, Session.SESSION_TRANSACTED); - Queue queue = session.createQueue(queueName); - createQueueOnBroker(session, queue); - - ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - managedQueue.setFlowResumeCapacity(DEFAULT_MESSAGE_SIZE * 2l); - managedQueue.setCapacity(DEFAULT_MESSAGE_SIZE * 3l); - - final ManagedConnection managedConnection = getConnectionMBean(); - - // Check that producer flow is not block before test - final CompositeDataSupport rowBeforeSend = getTheOneChannelRow(managedConnection); - assertFlowBlocked(rowBeforeSend, false); - - - // Check that producer flow does not become block too soon - sendMessage(session, queue, 3); - final CompositeDataSupport rowBeforeFull = getTheOneChannelRow(managedConnection); - assertFlowBlocked(rowBeforeFull, false); - - // Fourth message will over-fill the queue (but as we are not sending more messages, client thread wont't block) - sendMessage(session, queue, 1); - final CompositeDataSupport rowAfterFull = getTheOneChannelRow(managedConnection); - assertFlowBlocked(rowAfterFull, true); - - // Consume two to bring the queue down to the resume capacity - MessageConsumer consumer = session.createConsumer(queue); - assertNotNull("Could not receive first message", consumer.receive(1000)); - assertNotNull("Could not receive second message", consumer.receive(1000)); - session.commit(); - - // Check that producer flow is no longer blocked - final CompositeDataSupport rowAfterReceive = getTheOneChannelRow(managedConnection); - assertFlowBlocked(rowAfterReceive, false); - } - - private void createQueueOnBroker(Session session, Destination destination) throws JMSException - { - session.createConsumer(destination).close(); // Create a consumer only to cause queue creation - } - - private void assertChannelRowData(final CompositeData row, int unacknowledgedMessages, boolean isTransactional, boolean flowBlocked) - { - assertNotNull(row); - assertEquals("Unexpected transactional flag", isTransactional, row.get(ManagedConnection.TRANSACTIONAL)); - assertEquals("Unexpected unacknowledged message count", unacknowledgedMessages, row.get(ManagedConnection.UNACKED_COUNT)); - assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED)); - } - - private void assertFlowBlocked(final CompositeData row, boolean flowBlocked) - { - assertNotNull(row); - assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED)); - } - - private void checkAuthorisedId(ManagedConnection mBean) throws Exception - { - assertEquals("Unexpected authorized id", GUEST_USERNAME, mBean.getAuthorizedId()); - } - - private void checkClientVersion(ManagedConnection mBean) throws Exception - { - String expectedVersion = QpidProperties.getReleaseVersion(); - assertTrue(StringUtils.isNotBlank(expectedVersion)); - - assertEquals("Unexpected version", expectedVersion, mBean.getVersion()); - } - - private void checkClientId(ManagedConnection mBean) throws Exception - { - String expectedClientId = _connection.getClientID(); - assertTrue(StringUtils.isNotBlank(expectedClientId)); - - assertEquals("Unexpected ClientId", expectedClientId, mBean.getClientId()); - } - - private ManagedConnection getConnectionMBean() - { - List connections = getManagedConnections(); - assertNotNull("Connection MBean is not found", connections); - assertEquals("Unexpected number of connection mbeans", 1, connections.size()); - final ManagedConnection mBean = connections.get(0); - assertNotNull("Connection MBean is null", mBean); - return mBean; - } - - private List getManagedConnections() - { - return _jmxUtils.getManagedConnections(VIRTUAL_HOST_NAME); - } - - private CompositeDataSupport getTheOneChannelRow(final ManagedConnection mBean) throws Exception - { - TabularData channelsData = getChannelsDataWithRetry(mBean); - - assertEquals("Unexpected number of rows in channel table", 1, channelsData.size()); - - @SuppressWarnings("unchecked") - final Iterator rowItr = (Iterator) channelsData.values().iterator(); - final CompositeDataSupport row = rowItr.next(); - return row; - } - - private void receiveMessagesWithoutCommit(final MessageConsumer consumer, int numberOfMessages) throws Exception - { - for (int i = 0; i < numberOfMessages; i++) - { - final Message m = consumer.receive(1000l); - assertNotNull("Message " + i + " is not received", m); - } - } - - private TabularData getChannelsDataWithRetry(final ManagedConnection mBean) - throws IOException, JMException - { - TabularData channelsData = mBean.channels(); - int retries = 0; - while(channelsData.size() == 0 && retries < 5) - { - sleep(); - channelsData = mBean.channels(); - retries++; - } - return channelsData; - } - - private void sleep() - { - try - { - Thread.sleep(50); - } - catch (InterruptedException ie) - { - Thread.currentThread().interrupt(); - } - }} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java deleted file mode 100644 index ac6730638e..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.systest.management.jmx; - -import java.io.File; -import java.util.List; - -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.TabularData; - -import org.apache.qpid.management.common.mbeans.LoggingManagement; -import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBeanTest; -import org.apache.qpid.server.logging.log4j.LoggingFacadeTest; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.util.FileUtils; -import org.apache.qpid.util.LogMonitor; - -/** - * System test for Logging Management. These tests rely on value set within - * test-profiles/log4j-test.xml. - * - * @see LoggingManagementMBeanTest - * @see LoggingFacadeTest - * - */ -public class LoggingManagementTest extends QpidBrokerTestCase -{ - private JMXTestUtils _jmxUtils; - private LoggingManagement _loggingManagement; - private LogMonitor _monitor; - - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - - // System test normally run with log for4j test config from beneath test-profiles. We need to - // copy it as some of our tests write to this file. - - File tmpLogFile = File.createTempFile("log4j" + "." + getName(), ".xml"); - tmpLogFile.deleteOnExit(); - FileUtils.copy(_logConfigFile, tmpLogFile); - - _logConfigFile = tmpLogFile; - - super.setUp(); - _jmxUtils.open(); - - _loggingManagement = _jmxUtils.getLoggingManagement(); - _monitor = new LogMonitor(_outputFile); - } - - public void tearDown() throws Exception - { - try - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - } - finally - { - super.tearDown(); - } - } - - public void testViewEffectiveRuntimeLoggerLevels() throws Exception - { - final String qpidMainLogger = "org.apache.qpid"; - - TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); - final CompositeData row = table.get(new String[] {qpidMainLogger} ); - assertChannelRow(row, qpidMainLogger, "DEBUG"); - } - - public void testViewConfigFileLoggerLevels() throws Exception - { - final String operationalLoggingLogger = "qpid.message"; - - TabularData table = _loggingManagement.viewConfigFileLoggerLevels(); - final CompositeData row = table.get(new String[] {operationalLoggingLogger} ); - assertChannelRow(row, operationalLoggingLogger, "INFO"); - } - - public void testTurnOffOrgApacheQpidAtRuntime() throws Exception - { - final String logger = "org.apache.qpid"; - _monitor.markDiscardPoint(); - _loggingManagement.setRuntimeLoggerLevel(logger, "OFF"); - - List matches = _monitor.findMatches("Setting level to OFF for logger 'org.apache.qpid'"); - assertEquals(1, matches.size()); - - TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); - final CompositeData row1 = table.get(new String[] {logger} ); - assertChannelRow(row1, logger, "OFF"); - } - - public void testChangesToConfigFileBecomeEffectiveAfterReload() throws Exception - { - final String operationalLoggingLogger = "qpid.message"; - assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO"); - - _monitor.markDiscardPoint(); - _loggingManagement.setConfigFileLoggerLevel(operationalLoggingLogger, "OFF"); - - List matches = _monitor.findMatches("Setting level to OFF for logger 'qpid.message'"); - assertEquals(1, matches.size()); - - assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO"); - - _loggingManagement.reloadConfigFile(); - - assertEffectiveLoggingLevel(operationalLoggingLogger, "OFF"); - } - - private void assertEffectiveLoggingLevel(String operationalLoggingLogger, String expectedLevel) - { - TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels(); - final CompositeData row1 = table.get(new String[] {operationalLoggingLogger} ); - assertChannelRow(row1, operationalLoggingLogger, expectedLevel); - } - - private void assertChannelRow(final CompositeData row, String logger, String level) - { - assertNotNull("No row for " + logger, row); - assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME)); - assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL)); - } - -} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java deleted file mode 100644 index 47b38381c5..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java +++ /dev/null @@ -1,480 +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.systest.management.jmx; - -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedConnection; -import org.apache.qpid.management.common.mbeans.ManagedExchange; -import org.apache.qpid.server.logging.AbstractTestLogging; -import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; -import org.apache.qpid.test.utils.JMXTestUtils; - -import javax.jms.Connection; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.management.JMException; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -/** - * Test class to test if any change in the broker JMX code is affesting the management console - * There are some hardcoding of management feature names and parameter names to create a customized - * look in the console. - */ -public class ManagementActorLoggingTest extends AbstractTestLogging -{ - private JMXTestUtils _jmxUtils; - private boolean _closed = false; - - @Override - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - super.setUp(); - _jmxUtils.open(); - } - - @Override - public void tearDown() throws Exception - { - if(!_closed) - { - _jmxUtils.close(); - } - super.tearDown(); - } - - /** - * Description: - * When a connected client has its connection closed via the Management Console this will be logged as a CON-1002 message. - * Input: - * - * 1. Running Broker - * 2. Connected Client - * 3. Connection is closed via Management Console - * Output: - * - * CON-1002 : Close - * - * Validation Steps: - * 4. The CON ID is correct - * 5. This must be the last CON message for the Connection - * 6. It must be preceded by a CON-1001 for this Connection - * - * @throws Exception - {@see ManagedConnection.closeConnection and #getConnection} - * @throws java.io.IOException - if there is a problem reseting the log monitor - */ - public void testConnectionCloseViaManagement() throws IOException, Exception - { - //Create a connection to the broker - Connection connection = getConnection(); - - // Monitor the connection for an exception being thrown - // this should be a DisconnectionException but it is not this tests - // job to valiate that. Only use the exception as a synchronisation - // to check the log file for the Close message - final CountDownLatch exceptionReceived = new CountDownLatch(1); - connection.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException e) - { - //Failover being attempted. - exceptionReceived.countDown(); - } - }); - - //Remove the connection close from any 0-10 connections - _monitor.markDiscardPoint(); - - // Get a managedConnection - ManagedConnection mangedConnection = _jmxUtils.getManagedObject(ManagedConnection.class, "org.apache.qpid:type=VirtualHost.Connection,*"); - - //Close the connection - mangedConnection.closeConnection(); - - //Wait for the connection to close - assertTrue("Timed out waiting for conneciton to report close", - exceptionReceived.await(2, TimeUnit.SECONDS)); - - //Validate results - List results = waitAndFindMatches("CON-1002"); - - assertEquals("Unexpected Connection Close count", 1, results.size()); - } - - /** - * Description: - * Exchange creation is possible from the Management Console. - * When an exchanged is created in this way then a EXH-1001 create message - * is expected to be logged. - * Input: - * - * 1. Running broker - * 2. Connected Management Console - * 3. Exchange Created via Management Console - * Output: - * - * EXH-1001 : Create : [Durable] Type: Name: - * - * Validation Steps: - * 4. The EXH ID is correct - * 5. The correct tags are present in the message based on the create options - * - * @throws java.io.IOException - if there is a problem reseting the log monitor - * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} - */ - public void testCreateExchangeDirectTransientViaManagementConsole() throws IOException, JMException - { - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "direct", false); - - // Validate - - //1 - ID is correct - List results = waitAndFindMatches("EXH-1001"); - - assertEquals("More than one exchange creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - public void testCreateExchangeTopicTransientViaManagementConsole() throws IOException, JMException - { - //Remove any previous exchange declares - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "topic", false); - - // Validate - - //1 - ID is correct - List results = waitAndFindMatches("EXH-1001"); - - assertEquals("More than one exchange creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - - } - - public void testCreateExchangeFanoutTransientViaManagementConsole() throws IOException, JMException - { - //Remove any previous exchange declares - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "fanout", false); - - // Validate - - //1 - ID is correct - List results = waitAndFindMatches("EXH-1001"); - - assertEquals("More than one exchange creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - - } - - public void testCreateExchangeHeadersTransientViaManagementConsole() throws IOException, JMException - { - //Remove any previous exchange declares - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "headers", false); - - // Validate - - //1 - ID is correct - List results = waitAndFindMatches("EXH-1001"); - - assertEquals("More than one exchange creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct exchange name - assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName())); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - - } - - /** - * Description: - * Queue creation is possible from the Management Console. When a queue is created in this way then a QUE-1001 create message is expected to be logged. - * Input: - * - * 1. Running broker - * 2. Connected Management Console - * 3. Queue Created via Management Console - * Output: - * - * QUE-1001 : Create : Transient Owner: - * - * Validation Steps: - * 4. The QUE ID is correct - * 5. The correct tags are present in the message based on the create options - * - * @throws java.io.IOException - if there is a problem reseting the log monitor - * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} - */ - public void testCreateQueueTransientViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - // Validate - - List results = waitAndFindMatches("QUE-1001"); - - assertEquals("More than one queue creation found", 1, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct queue name - String subject = fromSubject(log); - assertEquals("Incorrect queue name created", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - /** - * Description: - * The ManagementConsole can be used to delete a queue. When this is done a QUE-1002 Deleted message must be logged. - * Input: - * - * 1. Running Broker - * 2. Queue created on the broker with no subscribers - * 3. Management Console connected - * 4. Queue is deleted via Management Console - * Output: - * - * QUE-1002 : Deleted - * - * Validation Steps: - * 5. The QUE ID is correct - * - * @throws java.io.IOException - if there is a problem reseting the log monitor - * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue} - */ - public void testQueueDeleteViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); - - managedBroker.deleteQueue(getName()); - - List results = waitAndFindMatches("QUE-1002"); - - assertEquals("More than one queue deletion found", 1, results.size()); - - String log = getLog(results.get(0)); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in delete", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - - } - - /** - * Description: - * The binding of a Queue and an Exchange is done via a Binding. When this Binding is created via the Management Console a BND-1001 Create message will be logged. - * Input: - * - * 1. Running Broker - * 2. Connected Management Console - * 3. Use Management Console to perform binding - * Output: - * - * BND-1001 : Create - * - * Validation Steps: - * 4. The BND ID is correct - * 5. This will be the first message for the given binding - * - * @throws java.io.IOException - if there is a problem reseting the log monitor - * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.createNewBinding} - */ - public void testBindingCreateOnDirectViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.direct"); - - managedExchange.createNewBinding(getName(), getName()); - - List results = waitAndFindMatches("BND-1001"); - - assertEquals("Unexpected number of bindings logged", 2, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - public void testBindingCreateOnTopicViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.topic"); - - managedExchange.createNewBinding(getName(), getName()); - - List results = waitAndFindMatches("BND-1001"); - - assertEquals("Unexpected number of bindings logged", 2, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - public void testBindingCreateOnFanoutViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createQueue("test", getName(), null, false); - - ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.fanout"); - - managedExchange.createNewBinding(getName(), getName()); - - List results = waitAndFindMatches("BND-1001"); - - assertEquals("Unexpected number of bindings logged", 2, results.size()); - - String log = getLogMessage(results, 0); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject)); - assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - - /** - * Description: - * Bindings can be deleted so that a queue can be rebound with a different set of values. This can be performed via the Management Console - * Input: - * - * 1. Running Broker - * 2. Management Console connected - * 3. Management Console is used to perform unbind. - * Output: - * - * BND-1002 : Deleted - * - * Validation Steps: - * 4. The BND ID is correct - * 5. There must have been a BND-1001 Create message first. - * 6. This will be the last message for the given binding - * - * @throws java.io.IOException - if there is a problem reseting the log monitor or an issue with the JMX Connection - * @throws javax.management.JMException - {@see #createExchange and ManagedBroker.unregisterExchange} - */ - public void testUnRegisterExchangeViaManagementConsole() throws IOException, JMException - { - //Remove any previous queue declares - _monitor.markDiscardPoint(); - - _jmxUtils.createExchange("test", getName(), "direct", false); - - ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test"); - - managedBroker.unregisterExchange(getName()); - - List results = waitAndFindMatches("EXH-1002"); - - assertEquals("More than one exchange deletion found", 1, results.size()); - - String log = getLog(results.get(0)); - - // Validate correct binding - String subject = fromSubject(log); - assertEquals("Incorrect exchange named in delete", "direct/" + getName(), AbstractTestLogSubject.getSlice("ex", subject)); - - // Validate it was a management actor. - String actor = fromActor(log); - assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng")); - } - -} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java deleted file mode 100644 index 6100d5a23e..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java +++ /dev/null @@ -1,317 +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.systest.management.jmx; - - -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.logging.AbstractTestLogging; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.util.LogMonitor; - -import java.io.File; -import java.util.List; - -/** - * Management Console Test Suite - * - * The Management Console test suite validates that the follow log messages as specified in the Functional Specification. - * - * This suite of tests validate that the management console messages occur correctly and according to the following format: - * - * MNG-1001 : Startup - * MNG-1002 : Starting : : Listening on port - * MNG-1003 : Shutting down : : port - * MNG-1004 : Ready - * MNG-1005 : Stopped - * MNG-1006 : Using SSL Keystore : - * MNG-1007 : Open : User - * MNG-1008 : Close : User - */ -public class ManagementLoggingTest extends AbstractTestLogging -{ - private static final String MNG_PREFIX = "MNG-"; - - public void setUp() throws Exception - { - setLogMessagePrefix(); - - // We either do this here or have a null check in tearDown. - // As when this test is run against profiles other than java it will NPE - _monitor = new LogMonitor(_outputFile); - //We explicitly do not call super.setUp as starting up the broker is - //part of the test case. - - } - - /** - * Description: - * Using the startup configuration validate that the management startup - * message is logged correctly. - * Input: - * Standard configuration with management enabled - * Output: - * - * MNG-1001 : Startup - * - * Constraints: - * This is the FIRST message logged by MNG - * Validation Steps: - * - * 1. The BRK ID is correct - * 2. This is the FIRST message logged by MNG - */ - public void testManagementStartupEnabled() throws Exception - { - // This test only works on java brokers - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(true, false); - - // Ensure we have received the MNG log msg. - waitForMessage("MNG-1001"); - - List results = findMatches(MNG_PREFIX); - // Validation - - assertTrue("MNGer message not logged", results.size() > 0); - - String log = getLogMessage(results, 0); - - //1 - validateMessageID("MNG-1001", log); - - //2 - //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J) - results = findMatches("MNG-1001"); - assertEquals("Unexpected startup message count.", - 2, results.size()); - - //3 - assertEquals("Startup log message is not 'Startup'.", "Startup", - getMessageString(log)); - } - } - - /** - * Description: - * Verify that when management is disabled in the configuration file the - * startup message is not logged. - * Input: - * Standard configuration with management disabled - * Output: - * NO MNG messages - * Validation Steps: - * - * 1. Validate that no MNG messages are produced. - */ - public void testManagementStartupDisabled() throws Exception - { - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(false, false); - - List results = findMatches(MNG_PREFIX); - // Validation - - assertEquals("MNGer messages logged", 0, results.size()); - } - } - - /** - * The two MNG-1002 messages are logged at the same time so lets test them - * at the same time. - * - * Description: - * Using the default configuration validate that the RMI Registry socket is - * correctly reported as being opened - * - * Input: - * The default configuration file - * Output: - * - * MESSAGE MNG-1002 : Starting : RMI Registry : Listening on port 8999 - * - * Constraints: - * The RMI ConnectorServer and Registry log messages do not have a prescribed order - * Validation Steps: - * - * 1. The MNG ID is correct - * 2. The specified port is the correct '8999' - * - * Description: - * Using the default configuration validate that the RMI ConnectorServer - * socket is correctly reported as being opened - * - * Input: - * The default configuration file - * Output: - * - * MESSAGE MNG-1002 : Starting : RMI ConnectorServer : Listening on port 9099 - * - * Constraints: - * The RMI ConnectorServer and Registry log messages do not have a prescribed order - * Validation Steps: - * - * 1. The MNG ID is correct - * 2. The specified port is the correct '9099' - */ - public void testManagementStartupRMIEntries() throws Exception - { - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(true, false); - - List results = waitAndFindMatches("MNG-1002"); - // Validation - - //There will be 4 startup messages (two via SystemOut, and two via Log4J) - assertEquals("Unexpected MNG-1002 message count", 4, results.size()); - - String log = getLogMessage(results, 0); - - //1 - validateMessageID("MNG-1002", log); - - //Check the RMI Registry port is as expected - int mPort = getManagementPort(getPort()); - assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log), - getMessageString(log).endsWith(String.valueOf(mPort))); - - log = getLogMessage(results, 2); - - //1 - validateMessageID("MNG-1002", log); - - // We expect the RMI Registry port (the defined 'management port') to be - // 100 lower than the JMX RMIConnector Server Port (the actual JMX server) - int jmxPort = mPort + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET; - assertTrue("JMX RMIConnectorServer port not as expected(" + jmxPort + ").:" + getMessageString(log), - getMessageString(log).endsWith(String.valueOf(jmxPort))); - } - } - - /** - * Description: - * Using the default configuration with SSL enabled for the management port the SSL Keystore path should be reported via MNG-1006 - * Input: - * Management SSL enabled default configuration. - * Output: - * - * MESSAGE MNG-1006 : Using SSL Keystore : test_resources/ssl/keystore.jks - * - * Validation Steps: - * - * 1. The MNG ID is correct - * 2. The keystore path is as specified in the configuration - */ - public void testManagementStartupSSLKeystore() throws Exception - { - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(true, true); - - List results = waitAndFindMatches("MNG-1006"); - - assertTrue("MNGer message not logged", results.size() > 0); - - String log = getLogMessage(results, 0); - - //1 - validateMessageID("MNG-1006", log); - - // Validate we only have two MNG-1002 (one via stdout, one via log4j) - results = findMatches("MNG-1006"); - assertEquals("Upexpected SSL Keystore message count", - 2, results.size()); - - // Validate the keystore path is as expected - assertTrue("SSL Keystore entry expected.:" + getMessageString(log), - getMessageString(log).endsWith(new File(getConfigurationStringProperty("management.ssl.keyStorePath")).getName())); - } - } - - /** - * Description: Tests the management connection open/close are logged correctly. - * - * Output: - * - * MESSAGE MNG-1007 : Open : User - * MESSAGE MNG-1008 : Close : User - * - * Validation Steps: - * - * 1. The MNG ID is correct - * 2. The message and username are correct - */ - public void testManagementUserOpenClose() throws Exception - { - if (isJavaBroker()) - { - startBrokerAndCreateMonitor(true, false); - - final JMXTestUtils jmxUtils = new JMXTestUtils(this); - List openResults = null; - List closeResults = null; - try - { - jmxUtils.setUp(); - jmxUtils.open(); - openResults = waitAndFindMatches("MNG-1007"); - } - finally - { - if (jmxUtils != null) - { - jmxUtils.close(); - closeResults = waitAndFindMatches("MNG-1008"); - } - } - - assertNotNull("Management Open results null", openResults.size()); - assertEquals("Management Open logged unexpected number of times", 1, openResults.size()); - - assertNotNull("Management Close results null", closeResults.size()); - assertEquals("Management Close logged unexpected number of times", 1, closeResults.size()); - - final String openMessage = getMessageString(getLogMessage(openResults, 0)); - assertTrue("Unexpected open message " + openMessage, openMessage.endsWith("Open : User admin")); - final String closeMessage = getMessageString(getLogMessage(closeResults, 0)); - assertTrue("Unexpected close message " + closeMessage, closeMessage.endsWith("Close : User admin")); - } - } - - private void startBrokerAndCreateMonitor(boolean managementEnabled, boolean useManagementSSL) throws Exception - { - //Ensure management is on - setConfigurationProperty("management.enabled", String.valueOf(managementEnabled)); - - if(useManagementSSL) - { - // This test requires we have an ssl connection - setConfigurationProperty("management.ssl.enabled", "true"); - } - - startBroker(); - - // Now we can create the monitor as _outputFile will now be defined - _monitor = new LogMonitor(_outputFile); - } -} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java deleted file mode 100644 index 79d04b239e..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java +++ /dev/null @@ -1,696 +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.systest.management.jmx; - -import org.apache.commons.lang.time.FastDateFormat; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.configuration.ClientProperties; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.NotificationCheckTest; -import org.apache.qpid.server.queue.SimpleAMQQueueTest; -import org.apache.qpid.test.client.destination.AddressBasedDestinationTest; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TextMessage; -import javax.management.Notification; -import javax.management.NotificationListener; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.TabularData; -import javax.naming.NamingException; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -/** - * Tests the JMX API for the Managed Queue. - * - */ -public class QueueManagementTest extends QpidBrokerTestCase -{ - - private static final Logger LOGGER = Logger.getLogger(QueueManagementTest.class); - - private static final String VIRTUAL_HOST = "test"; - private static final String TEST_QUEUE_DESCRIPTION = "my description"; - - private JMXTestUtils _jmxUtils; - private Connection _connection; - private Session _session; - - private String _sourceQueueName; - private String _destinationQueueName; - private Destination _sourceQueue; - private Destination _destinationQueue; - private ManagedQueue _managedSourceQueue; - private ManagedQueue _managedDestinationQueue; - - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - - super.setUp(); - _sourceQueueName = getTestQueueName() + "_src"; - _destinationQueueName = getTestQueueName() + "_dest"; - - createConnectionAndSession(); - - _sourceQueue = _session.createQueue(_sourceQueueName); - _destinationQueue = _session.createQueue(_destinationQueueName); - createQueueOnBroker(_sourceQueue); - createQueueOnBroker(_destinationQueue); - - _jmxUtils.open(); - - createManagementInterfacesForQueues(); - } - - public void tearDown() throws Exception - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - super.tearDown(); - } - - public void testQueueAttributes() throws Exception - { - Queue queue = _session.createQueue(getTestQueueName()); - createQueueOnBroker(queue); - - final String queueName = queue.getQueueName(); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals("Unexpected name", queueName, managedQueue.getName()); - assertEquals("Unexpected queue type", "standard", managedQueue.getQueueType()); - } - - public void testExclusiveQueueHasJmsClientIdAsOwner() throws Exception - { - Queue tmpQueue = _session.createTemporaryQueue(); - - final String queueName = tmpQueue.getQueueName(); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertNotNull(_connection.getClientID()); - assertEquals("Unexpected owner", _connection.getClientID(), managedQueue.getOwner()); - } - - public void testNonExclusiveQueueHasNoOwner() throws Exception - { - Queue nonExclusiveQueue = _session.createQueue(getTestQueueName()); - createQueueOnBroker(nonExclusiveQueue); - - final String queueName = nonExclusiveQueue.getQueueName(); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertNull("Unexpected owner", managedQueue.getOwner()); - } - - public void testSetNewQueueDescriptionOnExistingQueue() throws Exception - { - Queue queue = _session.createQueue(getTestQueueName()); - createQueueOnBroker(queue); - - final String queueName = queue.getQueueName(); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertNull("Unexpected description", managedQueue.getDescription()); - - managedQueue.setDescription(TEST_QUEUE_DESCRIPTION); - assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); - } - - public void testNewQueueWithDescription() throws Exception - { - String queueName = getTestQueueName(); - Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); - ((AMQSession)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); - } - - /** - * Requires persistent store. - */ - public void testQueueDescriptionSurvivesRestart() throws Exception - { - String queueName = getTestQueueName(); - Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); - - ((AMQSession)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); - - ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); - - restartBroker(); - - managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription()); - } - - /** - * Tests queue creation with {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument. Also tests - * that the attribute is exposed correctly through {@link ManagedQueue#getMaximumDeliveryCount()}. - */ - public void testCreateQueueWithMaximumDeliveryCountSet() throws Exception - { - final String queueName = getName(); - final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); - - final Integer deliveryCount = 1; - final Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount); - managedBroker.createNewQueue(queueName, null, true, arguments); - - // Ensure the queue exists - assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName("test", queueName)); - assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName)); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals("Unexpected maximum delivery count", deliveryCount, managedQueue.getMaximumDeliveryCount()); - } - - /** - * Requires 0-10 as relies on ADDR addresses. - * @see AddressBasedDestinationTest for the testing of message routing to the alternate exchange - */ - public void testGetSetAlternateExchange() throws Exception - { - String queueName = getTestQueueName(); - String altExchange = "amq.fanout"; - String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange); - Queue queue = _session.createQueue(addrWithAltExch); - - createQueueOnBroker(queue); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange()); - - String newAltExch = "amq.topic"; - managedQueue.setAlternateExchange(newAltExch); - assertEquals("Unexpected alternate exchange after set", newAltExch, managedQueue.getAlternateExchange()); - } - - /** - * Requires 0-10 as relies on ADDR addresses. - */ - public void testRemoveAlternateExchange() throws Exception - { - String queueName = getTestQueueName(); - String altExchange = "amq.fanout"; - String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange); - Queue queue = _session.createQueue(addrWithAltExch); - - createQueueOnBroker(queue); - - final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange()); - - managedQueue.setAlternateExchange(""); - assertNull("Unexpected alternate exchange after set", managedQueue.getAlternateExchange()); - } - - /** - * Requires persistent store - * Requires 0-10 as relies on ADDR addresses. - */ - public void testAlternateExchangeSurvivesRestart() throws Exception - { - String nonMandatoryExchangeName = "exch" + getName(); - - final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); - managedBroker.createNewExchange(nonMandatoryExchangeName, "fanout", true); - - String queueName1 = getTestQueueName() + "1"; - String altExchange1 = "amq.fanout"; - String addr1WithAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName1, altExchange1); - Queue queue1 = _session.createQueue(addr1WithAltExch); - - String queueName2 = getTestQueueName() + "2"; - String addr2WithoutAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue}}", queueName2); - Queue queue2 = _session.createQueue(addr2WithoutAltExch); - - createQueueOnBroker(queue1); - createQueueOnBroker(queue2); - - ManagedQueue managedQueue1 = _jmxUtils.getManagedQueue(queueName1); - assertEquals("Newly created queue1 does not have expected alternate exchange", altExchange1, managedQueue1.getAlternateExchange()); - - ManagedQueue managedQueue2 = _jmxUtils.getManagedQueue(queueName2); - assertNull("Newly created queue2 does not have expected alternate exchange", managedQueue2.getAlternateExchange()); - - String altExchange2 = nonMandatoryExchangeName; - managedQueue2.setAlternateExchange(altExchange2); - - restartBroker(); - - managedQueue1 = _jmxUtils.getManagedQueue(queueName1); - assertEquals("Queue1 does not have expected alternate exchange after restart", altExchange1, managedQueue1.getAlternateExchange()); - - managedQueue2 = _jmxUtils.getManagedQueue(queueName2); - assertEquals("Queue2 does not have expected updated alternate exchange after restart", altExchange2, managedQueue2.getAlternateExchange()); - } - - /** - * Tests the ability to receive queue alerts as JMX notifications. - * - * @see NotificationCheckTest - * @see SimpleAMQQueueTest#testNotificationFiredAsync() - * @see SimpleAMQQueueTest#testNotificationFiredOnEnqueue() - */ - public void testQueueNotification() throws Exception - { - final String queueName = getName(); - final long maximumMessageCount = 3; - - Queue queue = _session.createQueue(queueName); - createQueueOnBroker(queue); - - ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); - managedQueue.setMaximumMessageCount(maximumMessageCount); - - RecordingNotificationListener listener = new RecordingNotificationListener(1); - - _jmxUtils.addNotificationListener(_jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName), listener, null, null); - - // Send two messages - this should *not* trigger the notification - sendMessage(_session, queue, 2); - - assertEquals("Premature notification received", 0, listener.getNumberOfNotificationsReceived()); - - // A further message should trigger the message count alert - sendMessage(_session, queue, 1); - - listener.awaitExpectedNotifications(5, TimeUnit.SECONDS); - - assertEquals("Unexpected number of JMX notifications received", 1, listener.getNumberOfNotificationsReceived()); - - Notification notification = listener.getLastNotification(); - assertEquals("Unexpected notification message", "MESSAGE_COUNT_ALERT 3: Maximum count on queue threshold (3) breached.", notification.getMessage()); - } - - /** - * Tests {@link ManagedQueue#viewMessages(long, long)} interface. - */ - public void testViewSingleMessage() throws Exception - { - final List sentMessages = sendMessage(_session, _sourceQueue, 1); - syncSession(_session); - final Message sentMessage = sentMessages.get(0); - - assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue()); - - // Check the contents of the message - final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l); - assertEquals("Unexpected number of rows in table", 1, tab.size()); - final Iterator rowItr = (Iterator) tab.values().iterator(); - - final CompositeData row1 = rowItr.next(); - assertNotNull("Message should have AMQ message id", row1.get(ManagedQueue.MSG_AMQ_ID)); - assertEquals("Unexpected queue position", 1l, row1.get(ManagedQueue.MSG_QUEUE_POS)); - assertEquals("Unexpected redelivered flag", Boolean.FALSE, row1.get(ManagedQueue.MSG_REDELIVERED)); - - // Check the contents of header (encoded in a string array) - final String[] headerArray = (String[]) row1.get(ManagedQueue.MSG_HEADER); - assertNotNull("Expected message header array", headerArray); - final Map headers = headerArrayToMap(headerArray); - - final String expectedJMSMessageID = isBroker010() ? sentMessage.getJMSMessageID().replace("ID:", "") : sentMessage.getJMSMessageID(); - final String expectedFormattedJMSTimestamp = FastDateFormat.getInstance(ManagedQueue.JMSTIMESTAMP_DATETIME_FORMAT).format(sentMessage.getJMSTimestamp()); - assertEquals("Unexpected JMSMessageID within header", expectedJMSMessageID, headers.get("JMSMessageID")); - assertEquals("Unexpected JMSPriority within header", String.valueOf(sentMessage.getJMSPriority()), headers.get("JMSPriority")); - assertEquals("Unexpected JMSTimestamp within header", expectedFormattedJMSTimestamp, headers.get("JMSTimestamp")); - } - - /** - * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface. - */ - public void testMoveMessagesBetweenQueues() throws Exception - { - final int numberOfMessagesToSend = 10; - - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - - // Move first three messages to destination - long fromMessageId = amqMessagesIds.get(0); - long toMessageId = amqMessagesIds.get(2); - _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); - - assertEquals("Unexpected queue depth on destination queue after first move", 3, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after first move", 7, _managedSourceQueue.getMessageCount().intValue()); - - // Now move a further two messages to destination - fromMessageId = amqMessagesIds.get(7); - toMessageId = amqMessagesIds.get(8); - _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); - assertEquals("Unexpected queue depth on destination queue after second move", 5, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after second move", 5, _managedSourceQueue.getMessageCount().intValue()); - - assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8); - } - - /** - * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface. - */ - public void testCopyMessagesBetweenQueues() throws Exception - { - final int numberOfMessagesToSend = 10; - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - - // Copy first three messages to destination - long fromMessageId = amqMessagesIds.get(0); - long toMessageId = amqMessagesIds.get(2); - _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName); - - assertEquals("Unexpected queue depth on destination queue after first copy", 3, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after first copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - // Now copy a further two messages to destination - fromMessageId = amqMessagesIds.get(7); - toMessageId = amqMessagesIds.get(8); - _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName); - assertEquals("Unexpected queue depth on destination queue after second copy", 5, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after second copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8); - } - - public void testMoveMessagesBetweenQueuesWithActiveConsumerOnSourceQueue() throws Exception - { - setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString()); - Connection asyncConnection = getConnection(); - asyncConnection.start(); - - final int numberOfMessagesToSend = 50; - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - - long fromMessageId = amqMessagesIds.get(0); - long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1); - - CountDownLatch consumerReadToHalfwayLatch = new CountDownLatch(numberOfMessagesToSend / 2); - AtomicInteger totalConsumed = new AtomicInteger(0); - startAsyncConsumerOn(_sourceQueue, asyncConnection, consumerReadToHalfwayLatch, totalConsumed); - - boolean halfwayPointReached = consumerReadToHalfwayLatch.await(5000, TimeUnit.MILLISECONDS); - assertTrue("Did not read half of messages within time allowed", halfwayPointReached); - - _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); - - asyncConnection.stop(); - - // The exact number of messages moved will be non deterministic, as the number of messages processed - // by the consumer cannot be predicted. There is also the possibility that a message can remain - // on the source queue. This situation will arise if a message has been acquired by the consumer, but not - // yet delivered to the client application (i.e. MessageListener#onMessage()) when the Connection#stop() occurs. - // - // The number of messages moved + the number consumed + any messages remaining on source should - // *always* be equal to the number we originally sent. - - int numberOfMessagesReadByConsumer = totalConsumed.intValue(); - int numberOfMessagesOnDestinationQueue = _managedDestinationQueue.getMessageCount().intValue(); - int numberOfMessagesRemainingOnSourceQueue = _managedSourceQueue.getMessageCount().intValue(); - - LOGGER.debug("Async consumer read : " + numberOfMessagesReadByConsumer - + " Number of messages moved to destination : " + numberOfMessagesOnDestinationQueue - + " Number of messages remaining on source : " + numberOfMessagesRemainingOnSourceQueue); - assertEquals("Unexpected number of messages after move", numberOfMessagesToSend, numberOfMessagesReadByConsumer + numberOfMessagesOnDestinationQueue + numberOfMessagesRemainingOnSourceQueue); - } - - public void testMoveMessagesBetweenQueuesWithActiveConsumerOnDestinationQueue() throws Exception - { - setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString()); - Connection asyncConnection = getConnection(); - asyncConnection.start(); - - final int numberOfMessagesToSend = 50; - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - long fromMessageId = amqMessagesIds.get(0); - long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1); - - AtomicInteger totalConsumed = new AtomicInteger(0); - CountDownLatch allMessagesConsumedLatch = new CountDownLatch(numberOfMessagesToSend); - startAsyncConsumerOn(_destinationQueue, asyncConnection, allMessagesConsumedLatch, totalConsumed); - - _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName); - - allMessagesConsumedLatch.await(5000, TimeUnit.MILLISECONDS); - assertEquals("Did not consume all messages from destination queue", numberOfMessagesToSend, totalConsumed.intValue()); - } - - /** - * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface. - */ - public void testMoveMessageBetweenQueuesWithBrokerRestart() throws Exception - { - final int numberOfMessagesToSend = 1; - - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - restartBroker(); - - createManagementInterfacesForQueues(); - createConnectionAndSession(); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - - // Move messages to destination - long messageId = amqMessagesIds.get(0); - _managedSourceQueue.moveMessages(messageId, messageId, _destinationQueueName); - - assertEquals("Unexpected queue depth on destination queue after move", 1, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after move", 0, _managedSourceQueue.getMessageCount().intValue()); - - assertMessageIndicesOn(_destinationQueue, 0); - } - - /** - * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface. - */ - public void testCopyMessageBetweenQueuesWithBrokerRestart() throws Exception - { - final int numberOfMessagesToSend = 1; - - sendMessage(_session, _sourceQueue, numberOfMessagesToSend); - syncSession(_session); - assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue()); - - restartBroker(); - - createManagementInterfacesForQueues(); - createConnectionAndSession(); - - List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend); - - // Move messages to destination - long messageId = amqMessagesIds.get(0); - _managedSourceQueue.copyMessages(messageId, messageId, _destinationQueueName); - - assertEquals("Unexpected queue depth on destination queue after copy", 1, _managedDestinationQueue.getMessageCount().intValue()); - assertEquals("Unexpected queue depth on source queue after copy", 1, _managedSourceQueue.getMessageCount().intValue()); - - assertMessageIndicesOn(_destinationQueue, 0); - } - - @Override - public Message createNextMessage(Session session, int messageNumber) throws JMSException - { - Message message = session.createTextMessage(getContentForMessageNumber(messageNumber)); - message.setIntProperty(INDEX, messageNumber); - return message; - } - - private void startAsyncConsumerOn(Destination queue, Connection asyncConnection, - final CountDownLatch requiredNumberOfMessagesRead, final AtomicInteger totalConsumed) throws Exception - { - Session session = asyncConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); - MessageConsumer consumer = session.createConsumer(queue); - consumer.setMessageListener(new MessageListener() - { - - @Override - public void onMessage(Message arg0) - { - totalConsumed.incrementAndGet(); - requiredNumberOfMessagesRead.countDown(); - } - }); - } - - private void assertMessageIndicesOn(Destination queue, int... expectedIndices) throws Exception - { - MessageConsumer consumer = _session.createConsumer(queue); - - for (int i : expectedIndices) - { - TextMessage message = (TextMessage)consumer.receive(1000); - assertNotNull("Expected message with index " + i, message); - assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX)); - assertEquals("Expected message content", getContentForMessageNumber(i), message.getText()); - } - - assertNull("Unexpected message encountered", consumer.receive(1000)); - } - - private List getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception - { - final SortedSet messageIds = new TreeSet(); - - final TabularData tab = managedQueue.viewMessages(startIndex, endIndex); - final Iterator rowItr = (Iterator) tab.values().iterator(); - while(rowItr.hasNext()) - { - final CompositeData row = rowItr.next(); - long amqMessageId = (Long)row.get(ManagedQueue.MSG_AMQ_ID); - messageIds.add(amqMessageId); - } - - return new ArrayList(messageIds); - } - - /** - * - * Utility method to convert array of Strings in the form x = y into a - * map with key/value x => y. - * - */ - private Map headerArrayToMap(final String[] headerArray) - { - final Map headerMap = new HashMap(); - final List headerList = Arrays.asList(headerArray); - for (Iterator iterator = headerList.iterator(); iterator.hasNext();) - { - final String nameValuePair = iterator.next(); - final String[] nameValue = nameValuePair.split(" *= *", 2); - headerMap.put(nameValue[0], nameValue[1]); - } - return headerMap; - } - - private void createQueueOnBroker(Destination destination) throws JMSException - { - _session.createConsumer(destination).close(); // Create a consumer only to cause queue creation - } - - private void syncSession(Session session) throws Exception - { - ((AMQSession)session).sync(); - } - - private void createConnectionAndSession() throws JMSException, - NamingException - { - _connection = getConnection(); - _connection.start(); - _session = _connection.createSession(true, Session.SESSION_TRANSACTED); - } - - private void createManagementInterfacesForQueues() - { - _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName); - _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName); - } - - private String getContentForMessageNumber(int msgCount) - { - return "Message count " + msgCount; - } - - private final class RecordingNotificationListener implements NotificationListener - { - private final CountDownLatch _notificationReceivedLatch; - private final AtomicInteger _numberOfNotifications; - private final AtomicReference _lastNotification; - - private RecordingNotificationListener(int expectedNumberOfNotifications) - { - _notificationReceivedLatch = new CountDownLatch(expectedNumberOfNotifications); - _numberOfNotifications = new AtomicInteger(0); - _lastNotification = new AtomicReference(); - } - - @Override - public void handleNotification(Notification notification, Object handback) - { - _lastNotification.set(notification); - _numberOfNotifications.incrementAndGet(); - _notificationReceivedLatch.countDown(); - } - - public int getNumberOfNotificationsReceived() - { - return _numberOfNotifications.get(); - } - - public Notification getLastNotification() - { - return _lastNotification.get(); - } - - public void awaitExpectedNotifications(long timeout, TimeUnit timeunit) throws InterruptedException - { - _notificationReceivedLatch.await(timeout, timeunit); - } - } - -} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java deleted file mode 100644 index c3fff94923..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java +++ /dev/null @@ -1,204 +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.systest.management.jmx; - -import java.util.List; - -import javax.jms.Connection; -import javax.jms.MessageConsumer; -import javax.jms.Queue; -import javax.jms.Session; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedConnection; -import org.apache.qpid.management.common.mbeans.ServerInformation; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -public class StatisticsTest extends QpidBrokerTestCase -{ - private static final String TEST_USER = "admin"; - private static final String TEST_PASSWORD = "admin"; - private static final int MESSAGE_COUNT_TEST = 5; - private static final int MESSAGE_COUNT_DEV = 9; - - private JMXTestUtils _jmxUtils; - private Connection _test1, _dev; - private Session _testSession, _developmentSession; - private Queue _developmentQueue, _testQueue; - protected String _brokerUrl; - - @Override - public void setUp() throws Exception - { - _jmxUtils = new JMXTestUtils(this, TEST_USER, TEST_PASSWORD); - _jmxUtils.setUp(); - - super.setUp(); - - _brokerUrl = getBroker().toString(); - _test1 = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", "test"); - _dev = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", "development"); - _test1.start(); - _dev.start(); - - _testSession = _test1.createSession(true, Session.SESSION_TRANSACTED); - _developmentSession = _dev.createSession(true, Session.SESSION_TRANSACTED); - - _developmentQueue = _developmentSession.createQueue(getTestQueueName()); - _testQueue = _testSession.createQueue(getTestQueueName()); - - //Create queues by opening and closing consumers - final MessageConsumer testConsumer = _testSession.createConsumer(_testQueue); - testConsumer.close(); - final MessageConsumer developmentConsumer = _developmentSession.createConsumer(_developmentQueue); - developmentConsumer.close(); - - _jmxUtils.open(); - } - - @Override - public void tearDown() throws Exception - { - _jmxUtils.close(); - - super.tearDown(); - } - - public void testInitialStatisticValues() throws Exception - { - //Check initial values - checkSingleConnectionOnVHostStatistics("test", 0, 0, 0, 0); - checkVHostStatistics("test", 0, 0, 0, 0); - checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0); - checkVHostStatistics("development", 0, 0, 0, 0); - checkBrokerStatistics(0, 0, 0, 0); - } - - public void testSendOnSingleVHost() throws Exception - { - sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST); - - //Check values - checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - checkVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0); - checkVHostStatistics("development", 0, 0, 0, 0); - checkBrokerStatistics(MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - } - - public void testSendOnTwoVHosts() throws Exception - { - sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST); - sendMessagesAndSync(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV); - - //Check values - checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - checkVHostStatistics("test", MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0); - checkSingleConnectionOnVHostStatistics("development", MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0); - checkVHostStatistics("development", MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0); - checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, 0, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, 0); - } - - public void testSendAndConsumeOnSingleVHost() throws Exception - { - sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST); - consumeMessages(_testSession, _testQueue, MESSAGE_COUNT_TEST); - - //Check values - checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - checkVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - checkSingleConnectionOnVHostStatistics("development", 0, 0, 0, 0); - checkVHostStatistics("development", 0, 0, 0, 0); - checkBrokerStatistics(MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - } - - public void testSendAndConsumeOnTwoVHosts() throws Exception - { - sendMessagesAndSync(_testSession, _testQueue, MESSAGE_COUNT_TEST); - sendMessagesAndSync(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV); - consumeMessages(_testSession, _testQueue, MESSAGE_COUNT_TEST); - consumeMessages(_developmentSession, _developmentQueue, MESSAGE_COUNT_DEV); - - //Check values - checkSingleConnectionOnVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - checkVHostStatistics("test", MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE); - checkSingleConnectionOnVHostStatistics("development", MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE); - checkVHostStatistics("development", MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE); - checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE); - } - - private void sendMessagesAndSync(Session session, Queue queue, int numberOfMessages) throws Exception - { - //Send messages via connection on and sync - sendMessage(session, queue, numberOfMessages); - ((AMQSession)session).sync(); - } - - private void consumeMessages(Session session, Queue queue, int numberOfMessages) throws Exception - { - //consume the messages on the virtual host - final MessageConsumer consumer = session.createConsumer(queue); - for (int i = 0 ; i < numberOfMessages ; i++) - { - assertNotNull("an expected message was not received", consumer.receive(1500)); - } - session.commit(); - consumer.close(); - } - - private void checkSingleConnectionOnVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived) - { - List managedConnections = _jmxUtils.getManagedConnections(vHostName); - assertEquals(1, managedConnections.size()); - - ManagedConnection managedConnection = managedConnections.get(0); - - assertEquals(messagesSent, managedConnection.getTotalMessagesReceived()); - assertEquals(messagesReceived, managedConnection.getTotalMessagesDelivered()); - - assertEquals(dataSent, managedConnection.getTotalDataReceived()); - assertEquals(dataReceived, managedConnection.getTotalDataDelivered()); - } - - private void checkVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived) - { - ManagedBroker vhost = _jmxUtils.getManagedBroker(vHostName); - - assertEquals(messagesSent, vhost.getTotalMessagesReceived()); - assertEquals(messagesReceived, vhost.getTotalMessagesDelivered()); - - assertEquals(dataSent, vhost.getTotalDataReceived()); - assertEquals(dataReceived, vhost.getTotalDataDelivered()); - } - - private void checkBrokerStatistics(long messagesSent, long messagesReceived, long dataSent, long dataReceived) - { - ServerInformation broker = _jmxUtils.getServerInformation(); - - assertEquals(messagesSent, broker.getTotalMessagesReceived()); - assertEquals(messagesReceived, broker.getTotalMessagesDelivered()); - - assertEquals(dataSent, broker.getTotalDataReceived()); - assertEquals(dataReceived, broker.getTotalDataDelivered()); - } -} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java deleted file mode 100644 index 62b1b554a9..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java +++ /dev/null @@ -1,251 +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.systest.management.jmx; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; - -import javax.jms.Connection; -import javax.jms.JMSException; - -import org.apache.qpid.management.common.mbeans.UserManagement; -import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; -import org.apache.qpid.server.security.auth.database.PrincipalDatabase; -import org.apache.qpid.test.utils.JMXTestUtils; -import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.tools.security.Passwd; - -/** - * System test for User Management. - * - */ -public class UserManagementTest extends QpidBrokerTestCase -{ - private static final String TEST_NEWPASSWORD = "newpassword"; - private static final String TEST_PASSWORD = "password"; - private JMXTestUtils _jmxUtils; - private String _testUserName; - private File _passwordFile; - private UserManagement _userManagement; - private Passwd _passwd; - - public void setUp() throws Exception - { - _passwd = createPasswordEncodingUtility(); - _passwordFile = createTemporaryPasswordFileWithJmxAdminUser(); - - setConfigurationProperty("security.pd-auth-manager.principal-database.class", getPrincipalDatabaseImplClass().getName()); - setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.name", "passwordFile"); - setConfigurationProperty("security.pd-auth-manager.principal-database.attributes.attribute.value", _passwordFile.getAbsolutePath()); - - _jmxUtils = new JMXTestUtils(this); - _jmxUtils.setUp(); - - super.setUp(); - _jmxUtils.open(); - - _testUserName = getTestName() + System.currentTimeMillis(); - - _userManagement = _jmxUtils.getUserManagement(); - } - - - public void tearDown() throws Exception - { - try - { - if (_jmxUtils != null) - { - _jmxUtils.close(); - } - } - finally - { - super.tearDown(); - } - } - - public void testCreateUser() throws Exception - { - final int initialNumberOfUsers = _userManagement.viewUsers().size(); - assertFileDoesNotContainsPasswordForUser(_testUserName); - - boolean success = _userManagement.createUser(_testUserName, TEST_PASSWORD); - assertTrue("Should have been able to create new user " + _testUserName, success); - assertEquals("Unexpected number of users after add", initialNumberOfUsers + 1, _userManagement.viewUsers().size()); - - assertFileContainsPasswordForUser(_testUserName); - } - - public void testJmsLoginForNewUser() throws Exception - { - assertJmsConnectionFails(_testUserName, TEST_PASSWORD); - testCreateUser(); - - assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD); - } - - public void testDeleteUser() throws Exception - { - final int initialNumberOfUsers = _userManagement.viewUsers().size(); - - testCreateUser(); - - boolean success = _userManagement.deleteUser(_testUserName); - assertTrue("Should have been able to delete new user " + _testUserName, success); - assertEquals("Unexpected number of users after delete", initialNumberOfUsers, _userManagement.viewUsers().size()); - assertFileDoesNotContainsPasswordForUser(_testUserName); - } - - public void testJmsLoginNotPossibleForDeletedUser() throws Exception - { - testDeleteUser(); - - assertJmsConnectionFails(_testUserName, TEST_PASSWORD); - } - - public void testSetPassword() throws Exception - { - testCreateUser(); - - _userManagement.setPassword(_testUserName, TEST_NEWPASSWORD); - - assertFileContainsPasswordForUser(_testUserName); - } - - public void testJmsLoginForPasswordChangedUser() throws Exception - { - testSetPassword(); - - assertJmsConnectionSucceeds(_testUserName, TEST_NEWPASSWORD); - assertJmsConnectionFails(_testUserName, TEST_PASSWORD); - } - - public void testReload() throws Exception - { - writePasswordFile(_passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD, _testUserName, TEST_PASSWORD); - - assertJmsConnectionFails(_testUserName, TEST_PASSWORD); - - _userManagement.reloadData(); - - assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD); - } - - protected Passwd createPasswordEncodingUtility() - { - return new Passwd() - { - @Override - public String getOutput(String username, String password) - { - return username + ":" + password; - } - }; - } - - protected Class getPrincipalDatabaseImplClass() - { - return PlainPasswordFilePrincipalDatabase.class; - } - - private File createTemporaryPasswordFileWithJmxAdminUser() throws Exception - { - File passwordFile = File.createTempFile("passwd", "pwd"); - passwordFile.deleteOnExit(); - writePasswordFile(passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD); - return passwordFile; - } - - private void writePasswordFile(File passwordFile, String... userNamePasswordPairs) throws Exception - { - FileWriter writer = null; - try - { - writer = new FileWriter(passwordFile); - for (int i = 0; i < userNamePasswordPairs.length; i=i+2) - { - String username = userNamePasswordPairs[i]; - String password = userNamePasswordPairs[i+1]; - writer.append(_passwd.getOutput(username, password) + "\n"); - } - } - finally - { - writer.close(); - } - } - - - private void assertFileContainsPasswordForUser(String username) throws IOException - { - assertTrue("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username)); - } - - private void assertFileDoesNotContainsPasswordForUser(String username) throws IOException - { - assertFalse("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username)); - } - - private boolean passwordFileContainsUser(String username) throws IOException - { - BufferedReader reader = null; - try - { - reader = new BufferedReader(new FileReader(_passwordFile)); - String line = reader.readLine(); - while(line != null) - { - if (line.startsWith(username)) - { - return true; - } - line = reader.readLine(); - } - - return false; - } - finally - { - reader.close(); - } - } - - private void assertJmsConnectionSucceeds(String username, String password) throws Exception - { - Connection connection = getConnection(username, password); - assertNotNull(connection); - } - - private void assertJmsConnectionFails(String username, String password) throws Exception - { - try - { - getConnection(username, password); - fail("Exception not thrown"); - } - catch (JMSException e) - { - // PASS - } - } -} diff --git a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java b/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java deleted file mode 100644 index 84a66232ce..0000000000 --- a/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.systest.management.jmx; - -import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase; -import org.apache.qpid.server.security.auth.database.PrincipalDatabase; -import org.apache.qpid.tools.security.Passwd; - -public class UserManagementWithBase64MD5PasswordsTest extends UserManagementTest -{ - @Override - protected Passwd createPasswordEncodingUtility() - { - return new Passwd(); - } - - @Override - protected Class getPrincipalDatabaseImplClass() - { - return Base64MD5PasswordFilePrincipalDatabase.class; - } - -} diff --git a/java/broker/bin/qpid-server b/java/broker/bin/qpid-server index 382004c9f5..206ae6a225 100755 --- a/java/broker/bin/qpid-server +++ b/java/broker/bin/qpid-server @@ -33,8 +33,8 @@ if [ -z "$QPID_PNAME" ]; then export QPID_PNAME=" -DPNAME=QPBRKR" fi -# Set classpath to include the qpid-all manifest jar, and any jars supplied in lib/opt -QPID_LIBS="$QPID_HOME/lib/qpid-all.jar:$QPID_HOME/lib/opt/*" +# Set classpath to include the qpid-all manifest jar, plus jars in lib/plugins and lib/opt +QPID_LIBS="$QPID_HOME/lib/qpid-all.jar:$QPID_HOME/lib/plugins/*:$QPID_HOME/lib/opt/*" # Set other variables used by the qpid-run script before calling export JAVA=java \ diff --git a/java/broker/bin/qpid-server.bat b/java/broker/bin/qpid-server.bat index 6b7bbcb96e..0d0355c44a 100644 --- a/java/broker/bin/qpid-server.bat +++ b/java/broker/bin/qpid-server.bat @@ -76,8 +76,8 @@ echo Using CLASSPATH: %CLASSPATH% goto afterQpidClasspath :noQpidClasspath -echo Warning: Qpid classpath not set. CLASSPATH set to %QPID_HOME%\lib\qpid-all.jar -set CLASSPATH=%QPID_HOME%\lib\qpid-all.jar;%QPID_HOME%\lib\opt\* +echo Warning: Qpid classpath not set. CLASSPATH set to %QPID_HOME%\lib\qpid-all.jar;%QPID_HOME%\lib\plugins\*;%QPID_HOME%\lib\opt\* +set CLASSPATH=%QPID_HOME%\lib\qpid-all.jar;%QPID_HOME%\lib\plugins\*;%QPID_HOME%\lib\opt\* :afterQpidClasspath REM start parsing -run arguments diff --git a/java/broker/build.xml b/java/broker/build.xml index 938066728e..8581b7c639 100644 --- a/java/broker/build.xml +++ b/java/broker/build.xml @@ -20,7 +20,7 @@ --> - + @@ -28,23 +28,7 @@ - - - - - - - - - - - - - - - - - + @@ -64,9 +48,15 @@ - + + + + + + + - + diff --git a/java/broker/etc/broker_example.acl b/java/broker/etc/broker_example.acl index 45a48bda09..fc650801c8 100644 --- a/java/broker/etc/broker_example.acl +++ b/java/broker/etc/broker_example.acl @@ -19,24 +19,20 @@ ### EXAMPLE ACL V2 FILE ### NOTE: Rules are considered from top to bottom, and the first matching rule governs the decision. - -### DEFINE GROUPS ### - -#Define a 'messaging-users' group with users 'client' and 'server' in it -GROUP messaging-users client server - -#Define a group for management web console users -GROUP webadmins webadmin +### Rules may refer to users or groups. Groups are currently defined in the etc/groups file. ### JMX MANAGEMENT #### -# Allow everyone to perform read operations on the ServerInformation mbean -# This is used for items such as querying the management API and broker release versions. -ACL ALLOW ALL ACCESS METHOD component="ServerInformation" +# To use JMX management, first give the user/group ACCESS MANAGEMENT permission +ACL ALLOW administrators ACCESS MANAGEMENT +ACL ALLOW guest ACCESS MANAGEMENT -# Allow 'admin' all management operations. To reduce log file noise, only non-read-only operations are logged. -ACL ALLOW admin ACCESS METHOD -ACL ALLOW-LOG admin ALL METHOD +# Allow guest to perform read operations on the ServerInformation mbean +ACL ALLOW guest ACCESS METHOD component="ServerInformation" + +# Allow 'administrators' all management operations. To reduce log file noise, only non-read-only operations are logged. +ACL ALLOW administrators ACCESS METHOD +ACL ALLOW-LOG administrators ALL METHOD # Allow 'guest' to view logger levels, and use getter methods on LoggingManagement ACL ALLOW guest ACCESS METHOD component="LoggingManagement" name="viewEffectiveRuntimeLoggerLevels" @@ -49,17 +45,61 @@ ACL DENY-LOG ALL ACCESS METHOD component="UserManagement" ACL DENY-LOG ALL ACCESS METHOD component="ConfigurationManagement" ACL DENY-LOG ALL ACCESS METHOD component="LoggingManagement" -# Allow everyone to perform all read operations (using ALLOW rather than ALLOW-LOG to reduce log file noise) -# on the mbeans not listed in the DENY rules above +# Allow everyone to perform all read operations on the mbeans not listed in the DENY rules above ACL ALLOW ALL ACCESS METHOD +### WEB MANAGEMENT #### + +# To use web management, first give the user/group ACCESS MANAGEMENT permission +ACL ALLOW webadmins ACCESS MANAGEMENT + +# ACL for web management console admins +# All rules below are required for console admin users +# to perform create/update/delete operations +ACL ALLOW-LOG webadmins CREATE QUEUE +ACL ALLOW-LOG webadmins DELETE QUEUE +ACL ALLOW-LOG webadmins PURGE QUEUE +ACL ALLOW-LOG webadmins CREATE EXCHANGE +ACL ALLOW-LOG webadmins DELETE EXCHANGE +ACL ALLOW-LOG webadmins BIND EXCHANGE +ACL ALLOW-LOG webadmins UNBIND EXCHANGE +ACL ALLOW-LOG webadmins CREATE GROUP +ACL ALLOW-LOG webadmins DELETE GROUP +ACL ALLOW-LOG webadmins UPDATE GROUP +ACL ALLOW-LOG webadmins CREATE USER +ACL ALLOW-LOG webadmins DELETE USER +ACL ALLOW-LOG webadmins UPDATE USER + +ACL ALLOW-LOG webadmins UPDATE METHOD + +# at the moment only the following UPDATE METHOD rules are supported by web management console +#ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="moveMessages" +#ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="copyMessages" +#ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="deleteMessages" + ### MESSAGING ### +# The 'ACCESS VIRTUALHOST' rules below apply to messaging operations (as opposed to management operations) + +# Firewall examples + +# Deny access to all users from *.example.company1.com and *.example.company2.com +ACL DENY-LOG all ACCESS VIRTUALHOST from_hostname=".*\.example\.company1.com,.*\.example\.company2.com" -#Example permissions for request-response based messaging. +# Deny access to all users in the IP ranges 192.168.1.0-192.168.1.255 and 192.168.2.0-192.168.2.255, +# using the notation specified in RFC 4632, "Classless Inter-domain Routing (CIDR)" +ACL DENY-LOG messaging-users ACCESS VIRTUALHOST from_network="192.168.1.0/24,192.168.2.0/24" -#Allow 'messaging-users' group to connect to the virtualhost +# Deny access to all users in the IP ranges 192.169.1.0-192.169.1.255 and 192.169.2.0-192.169.2.255, +# using wildcard notation. +ACL DENY-LOG messaging-users ACCESS VIRTUALHOST from_network="192.169.1.*,192.169.2.*" + +# Allow 'messaging-users' group to connect to all virtualhosts ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST +# Deny messaging-users management +ACL DENY-LOG messaging-users ACCESS MANAGEMENT + + # Client side # Allow the 'client' user to publish requests to the request queue and create, consume from, and delete temporary reply queues. ACL ALLOW-LOG client CREATE QUEUE temporary="true" @@ -77,24 +117,8 @@ ACL ALLOW-LOG server CONSUME QUEUE name="example.RequestQueue" ACL ALLOW-LOG server BIND EXCHANGE ACL ALLOW-LOG server PUBLISH EXCHANGE name="amq.direct" routingKey="TempQueue*" -# ACL for web management console admins -# All rules below are required for console admin users -# to perform create/update/delete operations -ACL ALLOW-LOG webadmins CREATE QUEUE -ACL ALLOW-LOG webadmins DELETE QUEUE -ACL ALLOW-LOG webadmins PURGE QUEUE -ACL ALLOW-LOG webadmins CREATE EXCHANGE -ACL ALLOW-LOG webadmins DELETE EXCHANGE -ACL ALLOW-LOG webadmins BIND EXCHANGE -ACL ALLOW-LOG webadmins UNBIND EXCHANGE -ACL ALLOW-LOG webadmins UPDATE METHOD - -# at the moment only the following UPDATE METHOD rules are supported by web management console -#ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="moveMessages" -#ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="copyMessages" -#ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="deleteMessages" ### DEFAULT ### -#Deny all users from performing all operations +# Deny all users from performing all operations ACL DENY-LOG all all diff --git a/java/broker/etc/config.xml b/java/broker/etc/config.xml deleted file mode 100644 index 08c7c23d13..0000000000 --- a/java/broker/etc/config.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - ${QPID_HOME} - ${QPID_WORK} - ${prefix}/etc - - ${QPID_HOME}/lib/plugins - ${QPID_WORK}/cache - - - - - false - 5671 - false - /path/to/keystore.ks - keystorepass - - 5672 - 262144 - 262144 - - - true - - 8999 - - - - false - - ${conf}/qpid.keystore - password - - - false - - - - 65535 - en_US - - - - - - org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase - - - passwordFile - ${conf}/passwd - - - - - - - - - - false - - - ${conf}/virtualhosts.xml - - - 0 - 2.0 - - - true - - - ON - - - - diff --git a/java/broker/etc/groups b/java/broker/etc/groups new file mode 100644 index 0000000000..e3912ece99 --- /dev/null +++ b/java/broker/etc/groups @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# +# To define a group, use the format: +# +# .users=,,..., +# + +messaging-users.users=guest,client,server +administrators.users=admin +webadmins.users=webadmin + diff --git a/java/broker/etc/log4j.xml b/java/broker/etc/log4j.xml index b1b31248c1..71a13875a1 100644 --- a/java/broker/etc/log4j.xml +++ b/java/broker/etc/log4j.xml @@ -68,7 +68,7 @@ - + @@ -77,20 +77,20 @@ - + - + - - - + + + @@ -108,21 +108,14 @@ - - - - - - + - + diff --git a/java/broker/src/main/java/broker.bnd b/java/broker/src/main/java/broker.bnd index 4e799a1609..bf338543f7 100755 --- a/java/broker/src/main/java/broker.bnd +++ b/java/broker/src/main/java/broker.bnd @@ -17,7 +17,7 @@ # under the License. # -ver: 0.19.0 +ver: 0.21.0 Bundle-SymbolicName: qpid-broker Bundle-Version: ${ver} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/CompletionCode.java b/java/broker/src/main/java/org/apache/qpid/qmf/CompletionCode.java deleted file mode 100644 index 706ab3974a..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/CompletionCode.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.qmf; - -public enum CompletionCode -{ - OK, - UNKNOWN_OBJECT, - UNKNOWN_METHOD, - NOT_IMPLEMENTED, - INVALID_PARAMETER, - FEATURE_NOT_IMPLEMENTED, - FORBIDDEN, - EXCEPTION, - UNKNOWN_PACKAGE, - UNKNOWN_CLASS; -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java deleted file mode 100644 index 27ab580642..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java +++ /dev/null @@ -1,586 +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.qmf; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.ExchangeConfigType; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeReferrer; -import org.apache.qpid.server.exchange.ExchangeType; -import org.apache.qpid.server.exchange.topic.TopicExchangeResult; -import org.apache.qpid.server.exchange.topic.TopicMatcherResult; -import org.apache.qpid.server.exchange.topic.TopicNormalizer; -import org.apache.qpid.server.exchange.topic.TopicParser; -import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.virtualhost.HouseKeepingTask; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicLong; - -public class ManagementExchange implements Exchange, QMFService.Listener -{ - private static final AMQShortString QPID_MANAGEMENT = new AMQShortString("qpid.management"); - private static final AMQShortString QPID_MANAGEMENT_TYPE = new AMQShortString("management"); - - private VirtualHost _virtualHost; - - private final TopicParser _parser = new TopicParser(); - - private final Map _topicExchangeResults = - new ConcurrentHashMap(); - - private final Set _bindingSet = new CopyOnWriteArraySet(); - private UUID _id; - private UUID _qmfId; - private static final String AGENT_BANK = "0"; - - private int _bindingCountHigh; - private final AtomicLong _msgReceived = new AtomicLong(); - private final AtomicLong _bytesReceived = new AtomicLong(); - - private final CopyOnWriteArrayList _listeners = new CopyOnWriteArrayList(); - - //TODO : persist creation time - private long _createTime = System.currentTimeMillis(); - - - private class ManagementQueue implements BaseQueue - { - private final UUID QUEUE_ID = UUIDGenerator.generateRandomUUID(); - private final String NAME_AS_STRING = "##__mgmt_pseudo_queue__##" + QUEUE_ID.toString(); - private final AMQShortString NAME_AS_SHORT_STRING = new AMQShortString(NAME_AS_STRING); - - public void enqueue(ServerMessage message) throws AMQException - { - long size = message.getSize(); - - ByteBuffer buf = ByteBuffer.allocate((int) size); - - int offset = 0; - - while(offset < size) - { - offset += message.getContent(buf,offset); - } - - buf.flip(); - QMFCommandDecoder commandDecoder = new QMFCommandDecoder(getQMFService(),buf); - QMFCommand cmd; - while((cmd = commandDecoder.decode()) != null) - { - cmd.process(_virtualHost, message); - } - - } - - public void enqueue(ServerMessage message, boolean sync, PostEnqueueAction action) throws AMQException - { - enqueue(message); - } - - public void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException - { - enqueue(message); - } - - public boolean isDurable() - { - return false; - } - - public AMQShortString getNameShortString() - { - return NAME_AS_SHORT_STRING; - } - - @Override - public UUID getId() - { - return QUEUE_ID; - } - } - - - private final ManagementQueue _mgmtQueue = new ManagementQueue(); - - public ManagementExchange() - { - } - - public static final ExchangeType TYPE = new ExchangeType() - { - - public AMQShortString getName() - { - return QPID_MANAGEMENT_TYPE; - } - - public Class getExchangeClass() - { - return ManagementExchange.class; - } - - public ManagementExchange newInstance(UUID id, VirtualHost host, - AMQShortString name, - boolean durable, - int ticket, - boolean autoDelete) throws AMQException - { - ManagementExchange exch = new ManagementExchange(); - exch.initialise(id, host, name, durable, ticket, autoDelete); - return exch; - } - - public AMQShortString getDefaultExchangeName() - { - return QPID_MANAGEMENT; - } - }; - - - public AMQShortString getNameShortString() - { - return QPID_MANAGEMENT; - } - - public AMQShortString getTypeShortString() - { - return QPID_MANAGEMENT_TYPE; - } - - public void initialise(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) - throws AMQException - { - if(!QPID_MANAGEMENT.equals(name)) - { - throw new AMQException("Can't create more than one Management exchange"); - } - _virtualHost = host; - _id = id; - _virtualHost.scheduleHouseKeepingTask(_virtualHost.getBroker().getManagementPublishInterval(), new UpdateTask(_virtualHost)); - _qmfId = getConfigStore().createId(); - getConfigStore().addConfiguredObject(this); - getQMFService().addListener(this); - } - - public UUID getId() - { - return _id; - } - - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public ExchangeConfigType getConfigType() - { - return ExchangeConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return _virtualHost; - } - - public boolean isDurable() - { - return true; - } - - public VirtualHost getVirtualHost() - { - return _virtualHost; - } - - public String getName() - { - return QPID_MANAGEMENT.toString(); - } - - public ExchangeType getType() - { - return TYPE; - } - - public boolean isAutoDelete() - { - return false; - } - - public int getTicket() - { - return 0; - } - - public void close() throws AMQException - { - getConfigStore().removeConfiguredObject(this); - } - - public ConfigStore getConfigStore() - { - return getVirtualHost().getConfigStore(); - } - - public synchronized void addBinding(final Binding b) - { - - if(_bindingSet.add(b)) - { - AMQShortString routingKey = TopicNormalizer.normalize(new AMQShortString(b.getBindingKey())); - - TopicExchangeResult result = _topicExchangeResults.get(routingKey); - if(result == null) - { - result = new TopicExchangeResult(); - result.addUnfilteredQueue(b.getQueue()); - _parser.addBinding(routingKey, result); - _topicExchangeResults.put(routingKey,result); - } - else - { - result.addUnfilteredQueue(b.getQueue()); - } - - result.addBinding(b); - } - - for(BindingListener listener : _listeners) - { - listener.bindingAdded(this, b); - } - - if(_bindingSet.size() > _bindingCountHigh) - { - _bindingCountHigh = _bindingSet.size(); - } - - String bindingKey = b.getBindingKey(); - - if(bindingKey.startsWith("schema.") || bindingKey.startsWith("*.") || bindingKey.startsWith("#.")) - { - publishAllSchema(); - } - if(bindingKey.startsWith("console.") || bindingKey.startsWith("*.") || bindingKey.startsWith("#.")) - { - publishAllConsole(); - } - - } - - void publishAllConsole() - { - QMFService qmfService = getQMFService(); - - long sampleTime = System.currentTimeMillis(); - - for(QMFPackage pkg : qmfService.getSupportedSchemas()) - { - for(QMFClass qmfClass : pkg.getClasses()) - { - Collection qmfObjects = qmfService.getObjects(qmfClass); - - publishObjectsToConsole(sampleTime, qmfObjects); - } - - } - - } - - private QMFService getQMFService() - { - return _virtualHost.getApplicationRegistry().getQMFService(); - } - - void publishObjectsToConsole(final long sampleTime, - final Collection qmfObjects) - { - if(!qmfObjects.isEmpty() && hasBindings()) - { - QMFClass qmfClass = qmfObjects.iterator().next().getQMFClass(); - ArrayList commands = new ArrayList(); - - - for(QMFObject obj : qmfObjects) - { - commands.add(obj.asConfigInfoCmd(sampleTime)); - commands.add(obj.asInstrumentInfoCmd(sampleTime)); - } - - publishToConsole(qmfClass, commands); - } - } - - private void publishToConsole(final QMFClass qmfClass, final ArrayList commands) - { - if(!commands.isEmpty() && hasBindings()) - { - String routingKey = "console.obj.1." + AGENT_BANK + "." + qmfClass.getPackage().getName() + "." + qmfClass.getName(); - QMFMessage message = new QMFMessage(routingKey,commands.toArray(new QMFCommand[commands.size()])); - - Collection results = _parser.parse(new AMQShortString(routingKey)); - HashSet queues = new HashSet(); - for(TopicMatcherResult result : results) - { - TopicExchangeResult res = (TopicExchangeResult)result; - - for(Binding b : res.getBindings()) - { - b.incrementMatches(); - } - - queues.addAll(((TopicExchangeResult)result).getUnfilteredQueues()); - } - for(AMQQueue queue : queues) - { - try - { - queue.enqueue(message); - } - catch (AMQException e) - { - throw new RuntimeException(e); - } - } - } - } - - void publishAllSchema() - { - - } - - public synchronized void removeBinding(final Binding binding) - { - if(_bindingSet.remove(binding)) - { - AMQShortString bindingKey = TopicNormalizer.normalize(new AMQShortString(binding.getBindingKey())); - TopicExchangeResult result = _topicExchangeResults.get(bindingKey); - result.removeBinding(binding); - result.removeUnfilteredQueue(binding.getQueue()); - } - - for(BindingListener listener : _listeners) - { - listener.bindingRemoved(this, binding); - } - } - - public synchronized Collection getBindings() - { - return new ArrayList(_bindingSet); - } - - public ArrayList route(InboundMessage message) - { - ArrayList queues = new ArrayList(1); - _msgReceived.incrementAndGet(); - _bytesReceived.addAndGet(message.getSize()); - queues.add(_mgmtQueue); - return queues; - } - - public boolean isBound(String bindingKey, Map arguments, AMQQueue queue) - { - return false; //TODO - } - - public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue) - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isBound(AMQShortString routingKey, AMQQueue queue) - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isBound(AMQShortString routingKey) - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isBound(AMQQueue queue) - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean hasBindings() - { - return !_bindingSet.isEmpty(); - } - - public boolean isBound(String bindingKey, AMQQueue queue) - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isBound(String bindingKey) - { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - public void addCloseTask(final Task task) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - public void removeCloseTask(final Task task) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - - - public Exchange getAlternateExchange() - { - return null; - } - - public Map getArguments() - { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - public void setAlternateExchange(Exchange exchange) - { - - } - - public void removeReference(ExchangeReferrer exchange) - { - } - - public void addReference(ExchangeReferrer exchange) - { - } - - public boolean hasReferrers() - { - return true; - } - - - - private class UpdateTask extends HouseKeepingTask - { - public UpdateTask(VirtualHost vhost) - { - super(vhost); - } - - public void execute() - { - publishAllConsole(); - publishAllSchema(); - } - - } - - public void objectCreated(final QMFObject obj) - { - publishObjectsToConsole(System.currentTimeMillis(), Collections.singleton(obj)); - } - - public void objectDeleted(final QMFObject obj) - { - publishObjectsToConsole(System.currentTimeMillis(), Collections.singleton(obj)); - } - - public long getBindingCount() - { - return getBindings().size(); - } - - public long getBindingCountHigh() - { - return _bindingCountHigh; - } - - public long getMsgReceives() - { - return _msgReceived.get(); - } - - public long getMsgRoutes() - { - return getMsgReceives(); - } - - public long getMsgDrops() - { - return 0l; - } - - public long getByteReceives() - { - return _bytesReceived.get(); - } - - public long getByteRoutes() - { - return getByteReceives(); - } - - public long getByteDrops() - { - return 0l; - } - - public long getCreateTime() - { - return _createTime; - } - - public void addBindingListener(final BindingListener listener) - { - _listeners.add(listener); - } - - public void removeBindingListener(final BindingListener listener) - { - _listeners.remove(listener); - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java deleted file mode 100644 index 69284abc48..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java +++ /dev/null @@ -1,82 +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.qmf; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.codec.BBDecoder; - -import java.util.List; - -public class QMFBrokerRequestCommand extends QMFCommand -{ - - private static final Logger _qmfLogger = Logger.getLogger("qpid.qmf"); - - - public QMFBrokerRequestCommand(QMFCommandHeader header, BBDecoder buf) - { - super(header); - } - - public void process(VirtualHost virtualHost, ServerMessage message) - { - String exchangeName = message.getMessageHeader().getReplyToExchange(); - String queueName = message.getMessageHeader().getReplyToRoutingKey(); - - _qmfLogger.debug("Execute: " + this); - - QMFCommand[] commands = new QMFCommand[2]; - commands[0] = new QMFBrokerResponseCommand(this, virtualHost); - commands[1] = new QMFCommandCompletionCommand(this); - - Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); - - for(QMFCommand cmd : commands) - { - QMFMessage responseMessage = new QMFMessage(queueName, cmd); - - - List queues = exchange.route(responseMessage); - - - for(BaseQueue q : queues) - { - try - { - q.enqueue(responseMessage); - } - catch (AMQException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - } - - -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerResponseCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerResponseCommand.java deleted file mode 100644 index 34b2a851dc..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerResponseCommand.java +++ /dev/null @@ -1,45 +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.qmf; - -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.codec.BBEncoder; - -public class QMFBrokerResponseCommand extends QMFCommand -{ - private QMFCommandHeader _header; - private VirtualHost _virtualHost; - - public QMFBrokerResponseCommand(QMFBrokerRequestCommand qmfBrokerRequestCommand, VirtualHost virtualHost) - { - super( new QMFCommandHeader(qmfBrokerRequestCommand.getHeader().getVersion(), - qmfBrokerRequestCommand.getHeader().getSeq(), - QMFOperation.BROKER_RESPONSE)); - _virtualHost = virtualHost; - } - - public void encode(BBEncoder encoder) - { - super.encode(encoder); - encoder.writeUuid(_virtualHost.getBrokerId()); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClass.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClass.java deleted file mode 100644 index 7d566567a1..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClass.java +++ /dev/null @@ -1,156 +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.qmf; - -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -abstract public class QMFClass -{ - - - public enum Type - { - OBJECT((byte)1), - EVENT((byte)2); - - private final byte _value; - - Type(byte value) - { - _value = value; - } - - public byte getValue() - { - return _value; - } - } - - private final Type _type; - private QMFPackage _package; - private final String _name; - private byte[] _schemaHash; - - private Map _properties = new LinkedHashMap(); - private Map _statistics = new LinkedHashMap(); - private Map _methods = new LinkedHashMap(); - - - - public QMFClass(Type type, String name, byte[] schemaHash, List properties, - List statistics, List methods) - { - this(type, name, schemaHash); - setProperties(properties); - setStatistics(statistics); - setMethods(methods); - } - - - public QMFClass(Type type, String name, byte[] schemaHash) - - { - _type = type; - _name = name; - _schemaHash = schemaHash; - - } - - protected void setProperties(List properties) - { - for(QMFProperty prop : properties) - { - _properties.put(prop.getName(), prop); - } - } - - protected void setStatistics(List statistics) - { - for(QMFStatistic stat : statistics) - { - _statistics.put(stat.getName(), stat); - } - } - - - protected void setMethods(List methods) - { - for(QMFMethod method : methods) - { - _methods.put(method.getName(), method); - } - } - - public void setPackage(QMFPackage aPackage) - { - _package = aPackage; - for(QMFProperty prop : _properties.values()) - { - prop.setQMFClass(this); - } - // TODO Statisics, Methods - } - - public Type getType() - { - return _type; - } - - public QMFPackage getPackage() - { - return _package; - } - - public String getName() - { - return _name; - } - - public byte[] getSchemaHash() - { - return _schemaHash; - } - - public Collection getProperties() - { - return _properties.values(); - } - - public Collection getStatistics() - { - return _statistics.values(); - } - - public Collection getMethods() - { - return _methods.values(); - } - - public QMFMethod getMethod(String methodName) - { - return _methods.get(methodName); - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassIndicationCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassIndicationCommand.java deleted file mode 100644 index 613e1e5978..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassIndicationCommand.java +++ /dev/null @@ -1,48 +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.qmf; - -import org.apache.qpid.transport.codec.BBEncoder; - -public class QMFClassIndicationCommand extends QMFCommand -{ - private QMFClass _qmfClass; - - public QMFClassIndicationCommand(QMFClassQueryCommand qmfClassQueryCommand, QMFClass qmfClass) - { - super(new QMFCommandHeader(qmfClassQueryCommand.getHeader().getVersion(), - qmfClassQueryCommand.getHeader().getSeq(), - QMFOperation.CLASS_INDICATION)); - _qmfClass = qmfClass; - } - - - @Override - public void encode(BBEncoder encoder) - { - super.encode(encoder); - encoder.writeUint8(_qmfClass.getType().getValue()); - encoder.writeStr8(_qmfClass.getPackage().getName()); - encoder.writeStr8(_qmfClass.getName()); - encoder.writeBin128(_qmfClass.getSchemaHash()); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java deleted file mode 100644 index 5676bb7306..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java +++ /dev/null @@ -1,105 +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.qmf; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.codec.BBDecoder; - -import java.util.Collection; -import java.util.List; - -public class QMFClassQueryCommand extends QMFCommand -{ - private static final Logger _qmfLogger = Logger.getLogger("qpid.qmf"); - - - private final String _package; - - public QMFClassQueryCommand(QMFCommandHeader header, BBDecoder decoder) - { - super(header); - _package = decoder.readStr8(); - } - - public void process(VirtualHost virtualHost, ServerMessage message) - { - String exchangeName = message.getMessageHeader().getReplyToExchange(); - String routingKey = message.getMessageHeader().getReplyToRoutingKey(); - - _qmfLogger.debug("Execute: " + this); - - IApplicationRegistry appRegistry = virtualHost.getApplicationRegistry(); - QMFService service = appRegistry.getQMFService(); - - QMFPackage qmfPackage = service.getPackage(_package); - Collection qmfClasses = qmfPackage.getClasses(); - - QMFCommand[] commands = new QMFCommand[ qmfClasses.size() + 1 ]; - - int i = 0; - for(QMFClass qmfClass : qmfClasses) - { - commands[i++] = new QMFClassIndicationCommand(this, qmfClass); - } - commands[ commands.length - 1 ] = new QMFCommandCompletionCommand(this); - - - for(QMFCommand cmd : commands) - { - - - QMFMessage responseMessage = new QMFMessage(routingKey, cmd); - - Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); - - List queues = exchange.route(responseMessage); - - for(BaseQueue q : queues) - { - try - { - q.enqueue(responseMessage); - } - catch (AMQException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - } - - - @Override - public String toString() - { - return "QMFClassQueryCommand{" + - "package='" + _package + '\'' + - '}'; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommand.java deleted file mode 100644 index 4f143701af..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommand.java +++ /dev/null @@ -1,54 +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.qmf; - -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.codec.BBEncoder; - -public abstract class QMFCommand -{ - - private final QMFCommandHeader _header; - - protected QMFCommand(QMFCommandHeader header) - { - _header = header; - } - - - public void process(final VirtualHost virtualHost, final ServerMessage message) - { - throw new UnsupportedOperationException(); - } - - public void encode(BBEncoder encoder) - { - _header.encode(encoder); - - } - - public QMFCommandHeader getHeader() - { - return _header; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandCompletionCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandCompletionCommand.java deleted file mode 100644 index 397ad4090e..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandCompletionCommand.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.qmf; - -import org.apache.qpid.transport.codec.BBEncoder; - -public class QMFCommandCompletionCommand extends QMFCommand -{ - - private final CompletionCode _status; - private final String _text; - - public QMFCommandCompletionCommand(QMFCommand command) - { - this(command, CompletionCode.OK, ""); - } - public QMFCommandCompletionCommand(QMFCommand command, CompletionCode status, String text) - { - super( new QMFCommandHeader(command.getHeader().getVersion(), - command.getHeader().getSeq(), - QMFOperation.COMMAND_COMPLETION)); - - _status = status; - _text = text; - } - - - @Override - public void encode(BBEncoder encoder) - { - super.encode(encoder); - encoder.writeInt32(_status.ordinal()); - encoder.writeStr8(_text); - } - - @Override - public String toString() - { - return "QMFCommandCompletionCommand{" + - "status=" + _status + - ",text='" + _text + '\'' + - '}'; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandDecoder.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandDecoder.java deleted file mode 100644 index ac036dfa19..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandDecoder.java +++ /dev/null @@ -1,98 +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.qmf; - -import org.apache.qpid.transport.codec.BBDecoder; - -import java.nio.ByteBuffer; - -public class QMFCommandDecoder -{ - private BBDecoder _decoder; - - - private static final QMFOperation[] OP_CODES = new QMFOperation[256]; - private final QMFService _qmfService; - - static - { - for(QMFOperation op : QMFOperation.values()) - { - OP_CODES[op.getOpcode()] = op; - } - } - - public QMFCommandDecoder(final QMFService qmfService, ByteBuffer buf) - { - _qmfService = qmfService; - _decoder = new BBDecoder(); - _decoder.init(buf); - } - - public QMFCommand decode() - { - if(_decoder.hasRemaining()) - { - QMFCommandHeader header = readQMFHeader(); - - switch(header.getOperation()) - { - case BROKER_REQUEST: - return new QMFBrokerRequestCommand(header, _decoder); - case PACKAGE_QUERY: - return new QMFPackageQueryCommand(header, _decoder); - case CLASS_QUERY: - return new QMFClassQueryCommand(header, _decoder); - case SCHEMA_REQUEST: - return new QMFSchemaRequestCommand(header, _decoder); - case METHOD_REQUEST: - return new QMFMethodRequestCommand(header, _decoder, _qmfService); - case GET_QUERY: - return new QMFGetQueryCommand(header, _decoder); - default: - System.out.println("Unknown command"); - - } - - return null; - } - else - { - return null; - } - } - - private QMFCommandHeader readQMFHeader() - { - if(_decoder.readInt8() == (byte) 'A' - && _decoder.readInt8() == (byte) 'M') - { - byte version = _decoder.readInt8(); - short opCode = _decoder.readUint8(); - int seq = _decoder.readInt32(); - - return new QMFCommandHeader(version, seq, OP_CODES[opCode]); - - } - return null; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandHeader.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandHeader.java deleted file mode 100644 index c4d771317f..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandHeader.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.qmf; - -import org.apache.qpid.transport.codec.BBEncoder; - -public class QMFCommandHeader -{ - private final byte _version; - private final int _seq; - - private final QMFOperation _operation; - - public QMFCommandHeader(byte version, int seq, QMFOperation operation) - { - _version = version; - _seq = seq; - _operation = operation; - } - - public byte getVersion() - { - return _version; - } - - public int getSeq() - { - return _seq; - } - - public QMFOperation getOperation() - { - return _operation; - } - - public void encode(BBEncoder encoder) - { - encoder.writeUint8((short)'A'); - encoder.writeUint8((short)'M'); - encoder.writeInt8(_version); - encoder.writeUint8((short)_operation.getOpcode()); - encoder.writeInt32(_seq); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventClass.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventClass.java deleted file mode 100644 index ec471f18e8..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventClass.java +++ /dev/null @@ -1,42 +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.qmf; - -import java.util.List; - -public abstract class QMFEventClass extends QMFClass -{ - public QMFEventClass(String name, - byte[] schemaHash, - List properties, - List statistics, List methods) - { - super(Type.EVENT, name, schemaHash, properties, statistics, methods); - } - - public QMFEventClass(String name, byte[] schemaHash) - { - super(Type.EVENT, name, schemaHash); - } - - abstract public QMFEventSeverity getSeverity(); - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventCommand.java deleted file mode 100644 index 833ccfbca4..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventCommand.java +++ /dev/null @@ -1,47 +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.qmf; - -import org.apache.qpid.transport.codec.BBEncoder; - -public abstract class QMFEventCommand extends QMFCommand -{ - private final long _timestamp; - - protected QMFEventCommand() - { - super(new QMFCommandHeader((byte)'2',0, QMFOperation.EVENT)); - _timestamp = System.currentTimeMillis(); - } - - abstract public T getEventClass(); - - @Override - public void encode(final BBEncoder encoder) - { - super.encode(encoder); - encoder.writeStr8(getEventClass().getPackage().getName()); - encoder.writeStr8(getEventClass().getName()); - encoder.writeBin128(new byte[16]); - encoder.writeUint64(_timestamp * 1000000L); - encoder.writeUint8((short) getEventClass().getSeverity().ordinal()); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventSeverity.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventSeverity.java deleted file mode 100644 index 9f9c832732..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventSeverity.java +++ /dev/null @@ -1,33 +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.qmf; - -public enum QMFEventSeverity -{ - EMERGENCY, - ALERT, - CRITICAL, - ERROR, - WARN, - NOTICE, - INFORM, - DEBUG -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java deleted file mode 100644 index b1f958d4ba..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java +++ /dev/null @@ -1,205 +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.qmf; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.codec.BBDecoder; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -public class QMFGetQueryCommand extends QMFCommand -{ - - private static final Logger _qmfLogger = Logger.getLogger("qpid.qmf"); - - private String _className; - private String _packageName; - private UUID _objectId; - - public QMFGetQueryCommand(QMFCommandHeader header, BBDecoder decoder) - { - super(header); - - Map _map = decoder.readMap(); - _className = (String) _map.get("_class"); - _packageName = (String) _map.get("_package"); - byte[] objectIdBytes = (byte[]) _map.get("_objectId"); - - if(objectIdBytes != null) - { - long msb = 0; - long lsb = 0; - - for (int i = 0; i != 8; i++) - { - msb = (msb << 8) | (objectIdBytes[i] & 0xff); - } - for (int i = 8; i != 16; i++) - { - lsb = (lsb << 8) | (objectIdBytes[i] & 0xff); - } - _objectId = new UUID(msb, lsb); - } - else - { - _objectId = null; - } - - - } - - public void process(VirtualHost virtualHost, ServerMessage message) - { - String exchangeName = message.getMessageHeader().getReplyToExchange(); - String routingKey = message.getMessageHeader().getReplyToRoutingKey(); - - IApplicationRegistry appRegistry = virtualHost.getApplicationRegistry(); - QMFService service = appRegistry.getQMFService(); - - _qmfLogger.debug("Execute: " + this); - - List commands = new ArrayList(); - final long sampleTime = System.currentTimeMillis() * 1000000l; - - Collection packages; - - if(_packageName != null && _packageName.length() != 0) - { - QMFPackage qmfPackage = service.getPackage(_packageName); - if(qmfPackage == null) - { - packages = Collections.EMPTY_LIST; - } - else - { - packages = Collections.singleton(qmfPackage); - } - } - else - { - packages = service.getSupportedSchemas(); - } - - for(QMFPackage qmfPackage : packages) - { - - Collection qmfClasses; - - if(_className != null && _className.length() != 0) - { - QMFClass qmfClass = qmfPackage.getQMFClass(_className); - if(qmfClass == null) - { - qmfClasses = Collections.EMPTY_LIST; - } - else - { - qmfClasses = Collections.singleton(qmfClass); - } - } - else - { - qmfClasses = qmfPackage.getClasses(); - } - - - for(QMFClass qmfClass : qmfClasses) - { - Collection objects; - - if(_objectId != null) - { - QMFObject obj = service.getObjectById(qmfClass, _objectId); - if(obj == null) - { - objects = Collections.EMPTY_LIST; - } - else - { - objects = Collections.singleton(obj); - } - } - else - { - objects = service.getObjects(qmfClass); - } - - for(QMFObject object : objects) - { - - commands.add(object.asGetQueryResponseCmd(this, sampleTime)); - } - } - - - } - - - commands.add( new QMFCommandCompletionCommand(this)); - - - for(QMFCommand cmd : commands) - { - - _qmfLogger.debug("Respond: " + cmd); - QMFMessage responseMessage = new QMFMessage(routingKey, cmd); - - Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); - - List queues = exchange.route(responseMessage); - - for(BaseQueue q : queues) - { - try - { - q.enqueue(responseMessage); - } - catch (AMQException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - } - - @Override - public String toString() - { - return "QMFGetQueryCommand{" + - "packageName='" + _packageName + '\'' + - ", className='" + _className + '\'' + - ", objectId=" + _objectId + - '}'; - } -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java deleted file mode 100644 index 1b173c7e11..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.qmf; - -import java.util.Collection; -import java.util.Collections; -import org.apache.commons.lang.NotImplementedException; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.SessionConfig; -import org.apache.qpid.server.message.AMQMessageHeader; -import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.transport.codec.BBEncoder; - -import java.nio.ByteBuffer; -import java.util.Set; - -public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHeader -{ - - private ByteBuffer _content; - private String _routingKey; - - public QMFMessage(String routingKey, QMFCommand command) - { - this(routingKey, new QMFCommand[] { command }); - } - - - public QMFMessage(String routingKey, QMFCommand[] commands) - { - _routingKey = routingKey; - BBEncoder encoder = new BBEncoder(256); - - for(QMFCommand cmd : commands) - { - cmd.encode(encoder); - } - - - _content = encoder.buffer(); - } - - public String getRoutingKey() - { - return _routingKey; - } - - public AMQShortString getRoutingKeyShortString() - { - return AMQShortString.valueOf(_routingKey); - } - - public AMQMessageHeader getMessageHeader() - { - return this; - } - - public StoredMessage getStoredMessage() - { - throw new NotImplementedException(); - } - - public boolean isPersistent() - { - return false; - } - - public boolean isRedelivered() - { - return false; - } - - public long getSize() - { - return _content.limit(); - } - - public boolean isImmediate() - { - return false; - } - - public String getCorrelationId() - { - return null; - } - - public long getExpiration() - { - return 0; - } - - public String getUserId() - { - return null; - } - - public String getAppId() - { - return null; - } - - public String getMessageId() - { - return null; - } - - public String getMimeType() - { - return null; - } - - public String getEncoding() - { - return null; - } - - public byte getPriority() - { - return 4; - } - - public long getTimestamp() - { - return 0; - } - - public String getType() - { - return null; - } - - public String getReplyTo() - { - return null; - } - - public String getReplyToExchange() - { - return null; - } - - public String getReplyToRoutingKey() - { - return null; - } - - public Object getHeader(String name) - { - return null; - } - - public boolean containsHeaders(Set names) - { - return false; - } - - @Override - public Collection getHeaderNames() - { - return Collections.EMPTY_SET; - } - - public boolean containsHeader(String name) - { - return false; - } - - public MessageReference newReference() - { - return new QMFMessageReference(this); - } - - public long getMessageNumber() - { - return 0l; - } - - public long getArrivalTime() - { - return 0; - } - - public int getContent(ByteBuffer buf, int offset) - { - ByteBuffer src = _content.duplicate(); - src.position(offset); - src = src.slice(); - int len = src.remaining(); - if(len > buf.remaining()) - { - len = buf.remaining(); - } - - buf.put(src); - - return len; - } - - - public ByteBuffer getContent(int offset, int size) - { - ByteBuffer src = _content.duplicate(); - src.position(offset); - src = src.slice(); - src.limit(size); - return src; - } - - private static class QMFMessageReference extends MessageReference - { - public QMFMessageReference(QMFMessage message) - { - super(message); - } - - protected void onReference(QMFMessage message) - { - - } - - protected void onRelease(QMFMessage message) - { - - } - } - - public SessionConfig getSessionConfig() - { - return null; - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethod.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethod.java deleted file mode 100644 index 1d1cd24724..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethod.java +++ /dev/null @@ -1,157 +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.qmf; - -import org.apache.qpid.transport.codec.BBDecoder; -import org.apache.qpid.transport.codec.Encoder; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; - -public abstract class QMFMethod -{ - private final LinkedHashMap _map = new LinkedHashMap(); - private final List _arguments = new ArrayList(); - - private static final String NAME = "name"; - private static final String TYPE = "type"; - private static final String REF_PACKAGE = "refPackage"; - private static final String REF_CLASS = "refClass"; - private static final String UNIT = "unit"; - private static final String MIN = "min"; - private static final String MAX = "max"; - private static final String MAX_LENGTH = "maxlen"; - private static final String DESCRIPTION = "desc"; - private static final String DEFAULT = "default"; - private static final String DIRECTION = "dir"; - private static final String ARG_COUNT = "argCount"; - - - - public enum Direction - { - I, - O, - IO; - } - - public class Argument - { - private final LinkedHashMap _map = new LinkedHashMap(); - - public Argument(String name, QMFType type) - { - _map.put(NAME, name); - _map.put(TYPE, type.codeValue()); - } - - public void setRefPackage(String refPackage) - { - _map.put(REF_PACKAGE, refPackage); - } - - public void setRefClass(String refClass) - { - _map.put(REF_CLASS, refClass); - } - - public void setUnit(String unit) - { - _map.put(UNIT, unit); - } - - public void setMax(Number max) - { - _map.put(MAX, max); - } - - public void setMin(Number min) - { - _map.put(MIN, min); - } - - public void setMaxLength(int len) - { - _map.put(MAX_LENGTH, len); - } - - public void setDefault(Object dflt) - { - _map.put(DEFAULT, dflt); - } - - public void setDescription(String desc) - { - _map.put(DESCRIPTION, desc); - } - - public void setDirection(Direction direction) - { - _map.put(DIRECTION, direction.toString()); - } - - public void encode(Encoder encoder) - { - encoder.writeMap(_map); - } - - public String getName() - { - return (String) _map.get(NAME); - } - } - - public QMFMethod(String name, String description) - { - _map.put(NAME, name); - _map.put(ARG_COUNT, 0); - if(description != null) - { - _map.put(DESCRIPTION, description); - } - - } - - abstract public QMFMethodInvocation parse(final BBDecoder decoder); - - protected void addArgument(Argument arg) - { - _arguments.add(arg); - _map.put(ARG_COUNT, _arguments.size()); - } - - - public void encode(Encoder encoder) - { - encoder.writeMap(_map); - for(Argument arg : _arguments) - { - arg.encode(encoder); - } - } - - public String getName() - { - return (String) _map.get(NAME); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodInvocation.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodInvocation.java deleted file mode 100644 index 5348c2783f..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodInvocation.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.qmf; - -public interface QMFMethodInvocation -{ - QMFMethodResponseCommand execute(T obj, QMFMethodRequestCommand cmd); -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java deleted file mode 100644 index 1a4ce228b5..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.qmf; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.codec.BBDecoder; - -import java.util.List; -import java.util.UUID; - -public class QMFMethodRequestCommand extends QMFCommand -{ - private static final Logger _qmfLogger = Logger.getLogger("qpid.qmf"); - - private QMFMethodInvocation _methodInstance; - private QMFObject _object; - - public QMFMethodRequestCommand(final QMFCommandHeader header, final BBDecoder decoder, final QMFService qmfService) - { - super(header); - UUID objectId = decoder.readUuid(); - String packageName = decoder.readStr8(); - String className = decoder.readStr8(); - byte[] hash = decoder.readBin128(); - String methodName = decoder.readStr8(); - - QMFPackage qmfPackage = qmfService.getPackage(packageName); - QMFClass qmfClass = qmfPackage.getQMFClass(className); - _object = qmfService.getObjectById(qmfClass, objectId); - QMFMethod method = qmfClass.getMethod(methodName); - _methodInstance = method.parse(decoder); - - } - - public void process(final VirtualHost virtualHost, final ServerMessage message) - { - String exchangeName = message.getMessageHeader().getReplyToExchange(); - String queueName = message.getMessageHeader().getReplyToRoutingKey(); - - QMFCommand[] commands = new QMFCommand[2]; - - _qmfLogger.debug("Execute: " + _methodInstance + " on " + _object); - - commands[0] = _methodInstance.execute(_object, this); - commands[1] = new QMFCommandCompletionCommand(this); - - Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); - - for(QMFCommand cmd : commands) - { - QMFMessage responseMessage = new QMFMessage(queueName, cmd); - - - List queues = exchange.route(responseMessage); - - - for(BaseQueue q : queues) - { - try - { - q.enqueue(responseMessage); - } - catch (AMQException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodResponseCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodResponseCommand.java deleted file mode 100644 index 5fea014ad8..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodResponseCommand.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.qmf; - -import org.apache.qpid.transport.codec.BBEncoder; - -public class QMFMethodResponseCommand extends QMFCommand -{ - private CompletionCode _status = null; - private String _msg = null; - - public QMFMethodResponseCommand(final QMFMethodRequestCommand cmd, - CompletionCode status, - String msg) - { - super( new QMFCommandHeader(cmd.getHeader().getVersion(), - cmd.getHeader().getSeq(), - QMFOperation.METHOD_RESPONSE)); - - if(status == null) - { - _status = CompletionCode.OK; - } - else - { - _status = status; - } - - _msg = msg; - } - - public CompletionCode getStatus() - { - return _status; - } - - public String getStatusText() - { - return _msg; - } - - @Override - public void encode(final BBEncoder encoder) - { - super.encode(encoder); - - encoder.writeUint32(_status.ordinal()); - - if(_msg == null) - { - encoder.writeStr16(_status.toString()); - } - else - { - encoder.writeStr16(_msg); - } - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java deleted file mode 100644 index c3604dca44..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.qmf; - -import java.util.UUID; - -public abstract class QMFObject -{ - private long _deleteTime; - - public interface Delegate - { - UUID getQMFId(); - long getCreateTime(); - } - - - private D _delegate; - - protected QMFObject(D delegate) - { - _delegate = delegate; - } - - public D getDelegate() - { - return _delegate; - } - - abstract public C getQMFClass(); - - public final UUID getId() - { - return _delegate.getQMFId(); - } - - public final long getCreateTime() - { - return _delegate.getCreateTime(); - } - - public final void setDeleteTime() - { - _deleteTime = System.currentTimeMillis(); - } - - public final long getDeleteTime() - { - return _deleteTime; - } - - - - abstract public QMFCommand asConfigInfoCmd(long sampleTime); - abstract public QMFCommand asInstrumentInfoCmd(long sampleTime); - abstract public QMFCommand asGetQueryResponseCmd(final QMFGetQueryCommand queryCommand, long sampleTime); - - @Override - public String toString() - { - return _delegate.toString(); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFObjectClass.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObjectClass.java deleted file mode 100644 index fefdecb8d7..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFObjectClass.java +++ /dev/null @@ -1,44 +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.qmf; - -import java.util.List; - -public abstract class QMFObjectClass extends QMFClass -{ - public QMFObjectClass(String name, - byte[] schemaHash, - List properties, - List statistics, List methods) - { - super(QMFClass.Type.OBJECT, name, schemaHash, properties, statistics, methods); - } - - public QMFObjectClass(String name, byte[] schemaHash) - { - super(QMFClass.Type.OBJECT, name, schemaHash); - } - - - public abstract T newInstance(S delegate); - - -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFOperation.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFOperation.java deleted file mode 100644 index 6736b5d460..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFOperation.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.qmf; - -public enum QMFOperation -{ - - - BROKER_REQUEST('B'), - BROKER_RESPONSE('b'), // This message contains a broker response, sent from the broker in response to a broker request message. - COMMAND_COMPLETION('z'), // This message is sent to indicate the completion of a request. - CLASS_QUERY('Q'), // Class query messages are used by a management console to request a list of schema classes that are known by the management broker. - CLASS_INDICATION('q'), // Sent by the management broker, a class indication notifies the peer of the existence of a schema class. - SCHEMA_REQUEST('S'), // Schema request messages are used to request the full schema details for a class. - SCHEMA_RESPONSE('s'), // Schema response message contain a full description of the schema for a class. - HEARTBEAT_INDEICATION('h'), // This message is published once per publish-interval. It can be used by a client to positively determine which objects did not change during the interval (since updates are not published for objects with no changes). - CONFIG_INDICATION('c'), - INSTRUMENTATION_INDICATION('i'), - GET_QUERY_RESPONSE('g'), // This message contains a content record. Content records contain the values of all properties or statistics in an object. Such records are broadcast on a periodic interval if 1) a change has been made in the value of one of the elements, or 2) if a new management client has bound a queue to the management exchange. - GET_QUERY('G'), // Sent by a management console, a get query requests that the management broker provide content indications for all objects that match the query criteria. - METHOD_REQUEST('M'), // This message contains a method request. - METHOD_RESPONSE('m'), // This message contains a method result. - PACKAGE_QUERY('P'), // This message contains a schema package query request, requesting that the broker dump the list of known packages - PACKAGE_INDICATION('p'), // This message contains a schema package indication, identifying a package known by the broker - AGENT_ATTACH_REUQEST('A'), // This message is sent by a remote agent when it wishes to attach to a management broker - AGENT_ATTACH_RESPONSE('a'), // The management broker sends this response if an attaching remote agent is permitted to join - CONSOLE_ADDED_INDICATION('x'), // This message is sent to all remote agents by the management broker when a new console binds to the management exchange - EVENT('e') - ; - - - private final char _opcode; - - private static final QMFOperation[] OP_CODES = new QMFOperation[256]; - - - QMFOperation(char opcode) - { - _opcode = opcode; - } - - - public char getOpcode() - { - return _opcode; - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackage.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackage.java deleted file mode 100644 index 63b43475aa..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackage.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.qmf; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public class QMFPackage -{ - private final String _name; - private final Map _classes = new HashMap(); - - public QMFPackage(String name) - { - _name = name; - } - - public QMFPackage(String name, Collection classes) - { - this(name); - setClasses(classes); - } - - protected void setClasses(Collection classes) - { - for(QMFClass qmfClass : classes) - { - qmfClass.setPackage(this); - _classes.put(qmfClass.getName(), qmfClass); - } - } - - public String getName() - { - return _name; - } - - public Collection getClasses() - { - return _classes.values(); - } - - public QMFClass getQMFClass(String className) - { - return _classes.get(className); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageIndicationCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageIndicationCommand.java deleted file mode 100644 index 9c8fa1e2c6..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageIndicationCommand.java +++ /dev/null @@ -1,44 +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.qmf; - -import org.apache.qpid.transport.codec.BBEncoder; - -public class QMFPackageIndicationCommand extends QMFCommand -{ - private String _supportedSchema; - - public QMFPackageIndicationCommand(QMFPackageQueryCommand qmfPackageQueryCommand, String supportedSchema) - { - super( new QMFCommandHeader(qmfPackageQueryCommand.getHeader().getVersion(), - qmfPackageQueryCommand.getHeader().getSeq(), - QMFOperation.PACKAGE_INDICATION)); - _supportedSchema = supportedSchema; - - } - - public void encode(BBEncoder encoder) - { - super.encode(encoder); - encoder.writeStr8(_supportedSchema); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java deleted file mode 100644 index c74c7da252..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java +++ /dev/null @@ -1,98 +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.qmf; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.codec.BBDecoder; - -import java.util.Collection; -import java.util.List; - -public class QMFPackageQueryCommand extends QMFCommand -{ - - private static final Logger _qmfLogger = Logger.getLogger("qpid.qmf"); - - public QMFPackageQueryCommand(QMFCommandHeader header, BBDecoder decoder) - { - super(header); - } - - public void process(VirtualHost virtualHost, ServerMessage message) - { - String exchangeName = message.getMessageHeader().getReplyToExchange(); - String routingKey = message.getMessageHeader().getReplyToRoutingKey(); - - - IApplicationRegistry appRegistry = virtualHost.getApplicationRegistry(); - QMFService service = appRegistry.getQMFService(); - - Collection supportedSchemas = service.getSupportedSchemas(); - - QMFCommand[] commands = new QMFCommand[ supportedSchemas.size() + 1 ]; - - _qmfLogger.debug("Exectuting " + this); - - int i = 0; - for(QMFPackage p : supportedSchemas) - { - commands[i++] = new QMFPackageIndicationCommand(this, p.getName()); - } - commands[ commands.length - 1 ] = new QMFCommandCompletionCommand(this); - - - for(QMFCommand cmd : commands) - { - - QMFMessage responseMessage = new QMFMessage(routingKey, cmd); - - Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); - - List queues = exchange.route(responseMessage); - - - for(BaseQueue q : queues) - { - try - { - q.enqueue(responseMessage); - } - catch (AMQException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - } - - public String toString() - { - return "QMFPackageQueryCommand"; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFProperty.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFProperty.java deleted file mode 100644 index 5314466e2a..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFProperty.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.qmf; - -import org.apache.qpid.transport.codec.Encoder; - -import java.util.LinkedHashMap; -import java.util.Map; - -public class QMFProperty -{ - private final Map _map = new LinkedHashMap(); - private static final String NAME = "name"; - private static final String TYPE = "type"; - private static final String ACCESS = "access"; - private static final String INDEX = "index"; - private static final String OPTIONAL = "optional"; - private static final String REF_PACKAGE = "refPackage"; - private static final String REF_CLASS = "refClass"; - private static final String UNIT = "unit"; - private static final String MIN = "min"; - private static final String MAX = "max"; - private static final String MAX_LENGTH = "maxlen"; - private static final String DESCRIPTION = "desc"; - - - public static enum AccessCode - { - RC, - RW, - RO; - - public int codeValue() - { - return ordinal()+1; - } - } - - public QMFProperty(String name, QMFType type, AccessCode accessCode, boolean index, boolean optional) - { - _map.put(NAME, name); - _map.put(TYPE, type.codeValue()); - _map.put(ACCESS, accessCode.codeValue()); - _map.put(INDEX, index ? 1 : 0); - _map.put(OPTIONAL, optional ? 1 :0); - } - - - public void setQMFClass(QMFClass qmfClass) - { - } - - public void setReferencedClass(String refClass) - { - _map.put(REF_CLASS, refClass); - } - - public void setReferencedPackage(String refPackage) - { - _map.put(REF_CLASS, refPackage); - } - - - public String getName() - { - return (String) _map.get(NAME); - } - - - public void setUnit(String unit) - { - _map.put(UNIT, unit); - } - - public void setMin(Number min) - { - _map.put(MIN, min); - } - - public void setMax(Number max) - { - _map.put(MAX, max); - } - - public void setMaxLength(int maxlen) - { - _map.put(MAX_LENGTH, maxlen); - } - - - public void setDescription(String description) - { - _map.put(DESCRIPTION, description); - } - - public void encode(Encoder encoder) - { - encoder.writeMap(_map); - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java deleted file mode 100644 index 57c67fa7f6..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.qmf; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.codec.BBDecoder; - -import java.util.List; - -public class QMFSchemaRequestCommand extends QMFCommand -{ - private static final Logger _qmfLogger = Logger.getLogger("qpid.qmf"); - - private final String _packageName; - private final String _className; - private final byte[] _hash; - - public QMFSchemaRequestCommand(QMFCommandHeader header, BBDecoder decoder) - { - super(header); - _packageName = decoder.readStr8(); - _className = decoder.readStr8(); - _hash = decoder.readBin128(); - } - - public void process(VirtualHost virtualHost, ServerMessage message) - { - _qmfLogger.debug("Execute: " + this); - - String exchangeName = message.getMessageHeader().getReplyToExchange(); - String routingKey = message.getMessageHeader().getReplyToRoutingKey(); - - IApplicationRegistry appRegistry = virtualHost.getApplicationRegistry(); - QMFService service = appRegistry.getQMFService(); - - QMFPackage qmfPackage = service.getPackage(_packageName); - QMFClass qmfClass = qmfPackage.getQMFClass( _className ); - - QMFCommand[] commands = new QMFCommand[2]; - commands[0] = new QMFSchemaResponseCommand(this, qmfClass); - commands[ 1 ] = new QMFCommandCompletionCommand(this); - - - - Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); - - for(QMFCommand cmd : commands) - { - QMFMessage responseMessage = new QMFMessage(routingKey, cmd); - - - List queues = exchange.route(responseMessage); - - for(BaseQueue q : queues) - { - try - { - q.enqueue(responseMessage); - } - catch (AMQException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - } - - @Override - public String toString() - { - return "QMFSchemaRequestCommand{" + - " packageName='" + _packageName + '\'' + - ", className='" + _className + '\'' + - '}'; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaResponseCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaResponseCommand.java deleted file mode 100644 index 4bd0e41989..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaResponseCommand.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.qmf; - -import org.apache.qpid.transport.codec.BBEncoder; - -import java.util.Collection; - -public class QMFSchemaResponseCommand extends QMFCommand -{ - private final QMFClass _qmfClass; - - - public QMFSchemaResponseCommand(QMFSchemaRequestCommand qmfSchemaRequestCommand, QMFClass qmfClass) - { - super(new QMFCommandHeader(qmfSchemaRequestCommand.getHeader().getVersion(), - qmfSchemaRequestCommand.getHeader().getSeq(), - QMFOperation.SCHEMA_RESPONSE)); - _qmfClass = qmfClass; - } - - @Override - public void encode(BBEncoder encoder) - { - super.encode(encoder); - encoder.writeUint8(_qmfClass.getType().getValue()); - encoder.writeStr8(_qmfClass.getPackage().getName()); - encoder.writeStr8(_qmfClass.getName()); - encoder.writeBin128(_qmfClass.getSchemaHash()); - - Collection props = _qmfClass.getProperties(); - Collection stats = _qmfClass.getStatistics(); - Collection methods = _qmfClass.getMethods(); - - encoder.writeUint16(props.size()); - if(_qmfClass.getType() == QMFClass.Type.OBJECT) - { - encoder.writeUint16(stats.size()); - encoder.writeUint16(methods.size()); - } - - for(QMFProperty prop : props) - { - prop.encode(encoder); - } - - if(_qmfClass.getType() == QMFClass.Type.OBJECT) - { - - for(QMFStatistic stat : stats) - { - stat.encode(encoder); - } - - for(QMFMethod method : methods) - { - method.encode(encoder); - } - } - - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java deleted file mode 100644 index d713976919..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java +++ /dev/null @@ -1,2086 +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.qmf; - -import org.apache.qpid.AMQException; -import org.apache.qpid.common.Closeable; -import org.apache.qpid.qmf.schema.BrokerSchema; -import org.apache.qpid.server.configuration.*; -import org.apache.qpid.server.registry.IApplicationRegistry; - -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; - -public class QMFService implements ConfigStore.ConfigEventListener, Closeable -{ - - - private IApplicationRegistry _applicationRegistry; - private ConfigStore _configStore; - - - private final Map _supportedSchemas = new HashMap(); - private static final Map _qmfClassMapping = new HashMap(); - - static - { - _qmfClassMapping.put("system", SystemConfigType.getInstance()); - _qmfClassMapping.put("broker", BrokerConfigType.getInstance()); - _qmfClassMapping.put("vhost", VirtualHostConfigType.getInstance()); - _qmfClassMapping.put("exchange", ExchangeConfigType.getInstance()); - _qmfClassMapping.put("queue", QueueConfigType.getInstance()); - _qmfClassMapping.put("binding", BindingConfigType.getInstance()); - _qmfClassMapping.put("connection", ConnectionConfigType.getInstance()); - _qmfClassMapping.put("session", SessionConfigType.getInstance()); - _qmfClassMapping.put("subscription", SubscriptionConfigType.getInstance()); - _qmfClassMapping.put("link", LinkConfigType.getInstance()); - _qmfClassMapping.put("bridge", BridgeConfigType.getInstance()); - } - - private final Map _adapterMap = - new HashMap(); - private final Map _classMap = - new HashMap(); - - - private final ConcurrentHashMap> _managedObjects = - new ConcurrentHashMap>(); - - private final ConcurrentHashMap> _managedObjectsById = - new ConcurrentHashMap>(); - - private static final BrokerSchema PACKAGE = BrokerSchema.getPackage(); - - public static interface Listener - { - public void objectCreated(QMFObject obj); - public void objectDeleted(QMFObject obj); - } - - private final CopyOnWriteArrayList _listeners = new CopyOnWriteArrayList(); - - abstract class ConfigObjectAdapter, S extends QMFObjectClass, D extends QMFObject.Delegate, T extends ConfigObjectType, C extends ConfiguredObject> - { - private final T _type; - private final S _qmfClass; - - - protected ConfigObjectAdapter(final T type, final S qmfClass) - { - _type = type; - _qmfClass = qmfClass; - _adapterMap.put(type,this); - _classMap.put(type,qmfClass); - } - - public T getType() - { - return _type; - } - - public S getQMFClass() - { - return _qmfClass; - } - - protected final Q newInstance(D delegate) - { - return _qmfClass.newInstance(delegate); - } - - public abstract Q createQMFObject(C configObject); - } - - private ConfigObjectAdapter _systemObjectAdapter = - new ConfigObjectAdapter(SystemConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.SystemClass.class)) - { - - - public BrokerSchema.SystemObject createQMFObject( - final SystemConfig configObject) - { - return newInstance(new SystemDelegate(configObject)); - } - }; - - private ConfigObjectAdapter _brokerObjectAdapter = - new ConfigObjectAdapter(BrokerConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.BrokerClass.class)) - { - - public BrokerSchema.BrokerObject createQMFObject( - final BrokerConfig configObject) - { - return newInstance(new BrokerDelegate(configObject)); - } - }; - - private ConfigObjectAdapter _vhostObjectAdapter = - new ConfigObjectAdapter(VirtualHostConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.VhostClass.class)) - { - - public BrokerSchema.VhostObject createQMFObject( - final VirtualHostConfig configObject) - { - return newInstance(new VhostDelegate(configObject)); - } - }; - - - private ConfigObjectAdapter _exchangeObjectAdapter = - new ConfigObjectAdapter(ExchangeConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.ExchangeClass.class)) - { - - public BrokerSchema.ExchangeObject createQMFObject( - final ExchangeConfig configObject) - { - return newInstance(new ExchangeDelegate(configObject)); - } - }; - - - private ConfigObjectAdapter _queueObjectAdapter = - new ConfigObjectAdapter(QueueConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.QueueClass.class)) - { - - public BrokerSchema.QueueObject createQMFObject( - final QueueConfig configObject) - { - return newInstance(new QueueDelegate(configObject)); - } - }; - - - private ConfigObjectAdapter _bindingObjectAdapter = - new ConfigObjectAdapter(BindingConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.BindingClass.class)) - { - - public BrokerSchema.BindingObject createQMFObject( - final BindingConfig configObject) - { - return newInstance(new BindingDelegate(configObject)); - } - }; - - - private ConfigObjectAdapter _connectionObjectAdapter = - new ConfigObjectAdapter(ConnectionConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.ConnectionClass.class)) - { - - public BrokerSchema.ConnectionObject createQMFObject( - final ConnectionConfig configObject) - { - return newInstance(new ConnectionDelegate(configObject)); - } - }; - - - private ConfigObjectAdapter _sessionObjectAdapter = - new ConfigObjectAdapter(SessionConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.SessionClass.class)) - { - - public BrokerSchema.SessionObject createQMFObject( - final SessionConfig configObject) - { - return newInstance(new SessionDelegate(configObject)); - } - }; - - private ConfigObjectAdapter _subscriptionObjectAdapter = - new ConfigObjectAdapter(SubscriptionConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.SubscriptionClass.class)) - { - - public BrokerSchema.SubscriptionObject createQMFObject( - final SubscriptionConfig configObject) - { - return newInstance(new SubscriptionDelegate(configObject)); - } - }; - - - private ConfigObjectAdapter _linkObjectAdapter = - new ConfigObjectAdapter(LinkConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.LinkClass.class)) - { - - public BrokerSchema.LinkObject createQMFObject( - final LinkConfig configObject) - { - return newInstance(new LinkDelegate(configObject)); - } - }; - - - private ConfigObjectAdapter _bridgeObjectAdapter = - new ConfigObjectAdapter(BridgeConfigType.getInstance(), - PACKAGE.getQMFClassInstance(BrokerSchema.BridgeClass.class)) - { - - public BrokerSchema.BridgeObject createQMFObject( - final BridgeConfig configObject) - { - return newInstance(new BridgeDelegate(configObject)); - } - }; - - - - public QMFService(ConfigStore configStore, IApplicationRegistry applicationRegistry) - { - _configStore = configStore; - _applicationRegistry = applicationRegistry; - registerSchema(PACKAGE); - - for(ConfigObjectType v : _qmfClassMapping.values()) - { - configStore.addConfigEventListener(v, this); - } - init(); - } - - public void close() - { - for(ConfigObjectType v : _qmfClassMapping.values()) - { - _configStore.removeConfigEventListener(v, this); - } - _listeners.clear(); - - _managedObjects.clear(); - _managedObjectsById.clear(); - _classMap.clear(); - _adapterMap.clear(); - _supportedSchemas.clear(); - } - - - public void registerSchema(QMFPackage qmfPackage) - { - _supportedSchemas.put(qmfPackage.getName(), qmfPackage); - } - - - public Collection getSupportedSchemas() - { - return _supportedSchemas.values(); - } - - public QMFPackage getPackage(String aPackage) - { - return _supportedSchemas.get(aPackage); - } - - public void onEvent(final ConfiguredObject object, final ConfigStore.Event evt) - { - - switch (evt) - { - case CREATED: - manageObject(object); - break; - - case DELETED: - unmanageObject(object); - break; - } - } - - public QMFObject getObjectById(QMFClass qmfclass, UUID id) - { - ConcurrentHashMap map = _managedObjectsById.get(qmfclass); - if(map != null) - { - - UUID key = new UUID(id.getMostSignificantBits() & (0xFFFl << 48), id.getLeastSignificantBits()); - return map.get(key); - - } - else - { - return null; - } - } - - private void unmanageObject(final ConfiguredObject object) - { - final QMFClass qmfClass = _classMap.get(object.getConfigType()); - - if(qmfClass == null) - { - return; - } - - ConcurrentHashMap classObjects = _managedObjects.get(qmfClass); - if(classObjects != null) - { - QMFObject qmfObject = classObjects.remove(object); - if(qmfObject != null) - { - _managedObjectsById.get(qmfClass).remove(object.getQMFId()); - objectRemoved(qmfObject); - } - } - } - - private void manageObject(final ConfiguredObject object) - { - ConfigObjectAdapter adapter = _adapterMap.get(object.getConfigType()); - QMFObject qmfObject = adapter.createQMFObject(object); - final QMFClass qmfClass = qmfObject.getQMFClass(); - ConcurrentHashMap classObjects = _managedObjects.get(qmfClass); - - if(classObjects == null) - { - classObjects = new ConcurrentHashMap(); - if(_managedObjects.putIfAbsent(qmfClass, classObjects) != null) - { - classObjects = _managedObjects.get(qmfClass); - } - } - - ConcurrentHashMap classObjectsById = _managedObjectsById.get(qmfClass); - if(classObjectsById == null) - { - classObjectsById = new ConcurrentHashMap(); - if(_managedObjectsById.putIfAbsent(qmfClass, classObjectsById) != null) - { - classObjectsById = _managedObjectsById.get(qmfClass); - } - } - - classObjectsById.put(object.getQMFId(),qmfObject); - - if(classObjects.putIfAbsent(object, qmfObject) == null) - { - objectAdded(qmfObject); - } - } - - private void objectRemoved(final QMFObject qmfObject) - { - qmfObject.setDeleteTime(); - for(Listener l : _listeners) - { - l.objectDeleted(qmfObject); - } - } - - private void objectAdded(final QMFObject qmfObject) - { - for(Listener l : _listeners) - { - l.objectCreated(qmfObject); - } - } - - public void addListener(Listener l) - { - _listeners.add(l); - } - - public void removeListener(Listener l) - { - _listeners.remove(l); - } - - - private void init() - { - for(QMFClass qmfClass : PACKAGE.getClasses()) - { - ConfigObjectType configType = getConfigType(qmfClass); - if(configType != null) - { - Collection objects = _configStore.getConfiguredObjects(configType); - for(ConfiguredObject object : objects) - { - manageObject(object); - } - } - } - } - - public Collection getObjects(QMFClass qmfClass) - { - ConcurrentHashMap classObjects = _managedObjects.get(qmfClass); - if(classObjects != null) - { - return classObjects.values(); - } - else - { - return Collections.EMPTY_SET; - } - } - - private QMFObject adapt(final ConfiguredObject object) - { - if(object == null) - { - return null; - } - - QMFClass qmfClass = _classMap.get(object.getConfigType()); - ConcurrentHashMap classObjects = _managedObjects.get(qmfClass); - if(classObjects != null) - { - QMFObject qmfObject = classObjects.get(object); - if(qmfObject != null) - { - return qmfObject; - } - } - - return _adapterMap.get(object.getConfigType()).createQMFObject(object); - } - - private ConfigObjectType getConfigType(final QMFClass qmfClass) - { - return _qmfClassMapping.get(qmfClass.getName()); - } - - private static class SystemDelegate implements BrokerSchema.SystemDelegate - { - private final SystemConfig _obj; - - public SystemDelegate(final SystemConfig obj) - { - _obj = obj; - } - - public UUID getSystemId() - { - return _obj.getQMFId(); - } - - public String getOsName() - { - return _obj.getOperatingSystemName(); - } - - public String getNodeName() - { - return _obj.getNodeName(); - } - - public String getRelease() - { - return _obj.getOSRelease(); - } - - public String getVersion() - { - return _obj.getOSVersion(); - } - - public String getMachine() - { - return _obj.getOSArchitecture(); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public String toString() - { - return _obj.toString(); - } - } - - private class BrokerDelegate implements BrokerSchema.BrokerDelegate - { - private final BrokerConfig _obj; - - public BrokerDelegate(final BrokerConfig obj) - { - _obj = obj; - } - - public BrokerSchema.SystemObject getSystemRef() - { - return (BrokerSchema.SystemObject) adapt(_obj.getSystem()); - } - - public String getName() - { - return "amqp-broker"; - } - - public Integer getPort() - { - return _obj.getPort(); - } - - public Integer getWorkerThreads() - { - return _obj.getWorkerThreads(); - } - - public Integer getMaxConns() - { - return _obj.getMaxConnections(); - } - - public Integer getConnBacklog() - { - return _obj.getConnectionBacklogLimit(); - } - - public Long getStagingThreshold() - { - return _obj.getStagingThreshold(); - } - - public Boolean getMgmtPublish() - { - return true; - } - - public Integer getMgmtPubInterval() - { - return _obj.getManagementPublishInterval(); - } - - public String getVersion() - { - return _obj.getVersion(); - } - - public String getDataDir() - { - return _obj.getDataDirectory(); - } - - public Long getUptime() - { - return (System.currentTimeMillis() - _obj.getCreateTime()) * 1000000L; - } - - public Long getQueueCount() - { - // TODO - return 0L; - } - - public Long getMsgTotalEnqueues() - { - // TODO - return 0L; - } - - public Long getMsgTotalDequeues() - { - // TODO - return 0L; - } - - public Long getByteTotalEnqueues() - { - // TODO - return 0L; - } - - public Long getByteTotalDequeues() - { - // TODO - return 0L; - } - - public Long getMsgDepth() - { - // TODO - return 0L; - } - - public Long getByteDepth() - { - // TODO - return 0L; - } - - public Long getMsgPersistEnqueues() - { - // TODO - return 0L; - } - - public Long getMsgPersistDequeues() - { - // TODO - return 0L; - } - - public Long getBytePersistEnqueues() - { - // TODO - return 0L; - } - - public Long getBytePersistDequeues() - { - // TODO - return 0L; - } - - public Long getMsgTxnEnqueues() - { - // TODO - return 0L; - } - - public Long getMsgTxnDequeues() - { - // TODO - return 0L; - } - - public Long getByteTxnEnqueues() - { - // TODO - return 0L; - } - - public Long getByteTxnDequeues() - { - // TODO - return 0L; - } - - public Long getMsgFtdEnqueues() - { - // TODO - return 0L; - } - - public Long getMsgFtdDequeues() - { - // TODO - return 0L; - } - - public Long getByteFtdEnqueues() - { - // TODO - return 0L; - } - - public Long getByteFtdDequeues() - { - // TODO - return 0L; - } - - public Long getMsgFtdDepth() - { - // TODO - return 0L; - } - - public Long getByteFtdDepth() - { - // TODO - return 0L; - } - - public Long getReleases() - { - // TODO - return 0L; - } - - public Long getAcquires() - { - // TODO - return 0L; - } - - public Long getDiscardsNoRoute() - { - // TODO - return 0L; - } - - public Long getDiscardsTtl() - { - // TODO - return 0L; - } - - public Long getDiscardsRing() - { - // TODO - return 0L; - } - - public Long getDiscardsLvq() - { - // TODO - return 0L; - } - - public Long getDiscardsOverflow() - { - // TODO - return 0L; - } - - public Long getDiscardsSubscriber() - { - // TODO - return 0L; - } - - public Long getDiscardsPurge() - { - // TODO - return 0L; - } - - public Long getReroutes() - { - // TODO - return 0L; - } - - public Long getAbandoned() - { - // TODO - return 0L; - } - - public Long getAbandonedViaAlt() - { - // TODO - return 0L; - } - - public BrokerSchema.BrokerClass.EchoMethodResponseCommand echo(final BrokerSchema.BrokerClass.EchoMethodResponseCommandFactory factory, - final Long sequence, - final String body) - { - return factory.createResponseCommand(sequence, body); - } - - public BrokerSchema.BrokerClass.ConnectMethodResponseCommand connect(final BrokerSchema.BrokerClass.ConnectMethodResponseCommandFactory factory, - final String host, - final Long port, - final Boolean durable, - final String authMechanism, - final String username, - final String password, - final String transport) - { - _obj.createBrokerConnection(transport, host, port.intValue(), durable, authMechanism, username, password); - - return factory.createResponseCommand(); - } - - public BrokerSchema.BrokerClass.QueueMoveMessagesMethodResponseCommand queueMoveMessages(final BrokerSchema.BrokerClass.QueueMoveMessagesMethodResponseCommandFactory factory, - final String srcQueue, - final String destQueue, - final Long qty, - final Map filter) // TODO: move based on group identifier - { - // TODO - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.BrokerClass.GetLogLevelMethodResponseCommand getLogLevel(final BrokerSchema.BrokerClass.GetLogLevelMethodResponseCommandFactory factory) - { - // TODO: The Java broker has numerous loggers, so we can't really implement this method properly. - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.BrokerClass.SetLogLevelMethodResponseCommand setLogLevel(final BrokerSchema.BrokerClass.SetLogLevelMethodResponseCommandFactory factory, String level) - { - // TODO: The Java broker has numerous loggers, so we can't really implement this method properly. - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.BrokerClass.GetTimestampConfigMethodResponseCommand getTimestampConfig(final BrokerSchema.BrokerClass.GetTimestampConfigMethodResponseCommandFactory factory) - { - // TODO: timestamp support - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.BrokerClass.SetTimestampConfigMethodResponseCommand setTimestampConfig(final BrokerSchema.BrokerClass.SetTimestampConfigMethodResponseCommandFactory factory, - final java.lang.Boolean receive) - { - // TODO: timestamp support - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.BrokerClass.CreateMethodResponseCommand create(final BrokerSchema.BrokerClass.CreateMethodResponseCommandFactory factory, - final String type, - final String name, - final Map properties, - final java.lang.Boolean lenient) - { - //TODO: - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.BrokerClass.DeleteMethodResponseCommand delete(final BrokerSchema.BrokerClass.DeleteMethodResponseCommandFactory factory, - final String type, - final String name, - final Map options) - { - //TODO: - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.BrokerClass.QueryMethodResponseCommand query(final BrokerSchema.BrokerClass.QueryMethodResponseCommandFactory factory, - final String type, - final String name) - { - //TODO: - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public String toString() - { - return _obj.toString(); - } - } - - private class VhostDelegate implements BrokerSchema.VhostDelegate - { - private final VirtualHostConfig _obj; - - public VhostDelegate(final VirtualHostConfig obj) - { - _obj = obj; - } - - public BrokerSchema.BrokerObject getBrokerRef() - { - return (BrokerSchema.BrokerObject) adapt(_obj.getBroker()); - } - - public String getName() - { - return _obj.getName(); - } - - public String getFederationTag() - { - return _obj.getFederationTag(); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public String toString() - { - return _obj.toString(); - } - } - - private class ExchangeDelegate implements BrokerSchema.ExchangeDelegate - { - private final ExchangeConfig _obj; - - public ExchangeDelegate(final ExchangeConfig obj) - { - _obj = obj; - } - - public BrokerSchema.VhostObject getVhostRef() - { - return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); - } - - public String getName() - { - return _obj.getName(); - } - - public String getType() - { - return _obj.getType().getName().toString(); - } - - public Boolean getDurable() - { - return _obj.isDurable(); - } - - public Boolean getAutoDelete() - { - return _obj.isAutoDelete(); - } - - public BrokerSchema.ExchangeObject getAltExchange() - { - if(_obj.getAlternateExchange() != null) - { - return (BrokerSchema.ExchangeObject) adapt(_obj.getAlternateExchange()); - } - else - { - return null; - } - } - - public Map getArguments() - { - return _obj.getArguments(); - } - - public Long getProducerCount() - { - // TODO - return 0l; - } - - public Long getProducerCountHigh() - { - // TODO - return 0l; - } - - public Long getProducerCountLow() - { - // TODO - return 0l; - } - - public Long getBindingCount() - { - return _obj.getBindingCount(); - } - - public Long getBindingCountHigh() - { - return _obj.getBindingCountHigh(); - } - - public Long getBindingCountLow() - { - // TODO - return 0l; - } - - public Long getMsgReceives() - { - return _obj.getMsgReceives(); - } - - public Long getMsgDrops() - { - return getMsgReceives() - getMsgRoutes(); - } - - public Long getMsgRoutes() - { - return _obj.getMsgRoutes(); - } - - public Long getByteReceives() - { - return _obj.getByteReceives(); - } - - public Long getByteDrops() - { - return getByteReceives() - getByteRoutes(); - } - - public Long getByteRoutes() - { - return _obj.getByteRoutes(); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public String toString() - { - return _obj.toString(); - } - } - - private class QueueDelegate implements BrokerSchema.QueueDelegate - { - private final QueueConfig _obj; - - public QueueDelegate(final QueueConfig obj) - { - _obj = obj; - } - - public BrokerSchema.VhostObject getVhostRef() - { - return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); - } - - public String getName() - { - return _obj.getName(); - } - - public Boolean getDurable() - { - return _obj.isDurable(); - } - - public Boolean getAutoDelete() - { - return _obj.isAutoDelete(); - } - - public Boolean getExclusive() - { - return _obj.isExclusive(); - } - - public BrokerSchema.ExchangeObject getAltExchange() - { - if(_obj.getAlternateExchange() != null) - { - return (BrokerSchema.ExchangeObject) adapt(_obj.getAlternateExchange()); - } - else - { - return null; - } - } - - public Long getMsgTotalEnqueues() - { - return _obj.getReceivedMessageCount(); - } - - public Long getMsgTotalDequeues() - { - return _obj.getMessageDequeueCount(); - } - - public Long getMsgTxnEnqueues() - { - return _obj.getMsgTxnEnqueues(); - } - - public Long getMsgTxnDequeues() - { - return _obj.getMsgTxnDequeues(); - } - - public Long getMsgPersistEnqueues() - { - return _obj.getPersistentMsgEnqueues(); - } - - public Long getMsgPersistDequeues() - { - return _obj.getPersistentMsgDequeues(); - } - - public Long getMsgDepth() - { - return (long) _obj.getMessageCount(); - } - - public Long getByteDepth() - { - return _obj.getQueueDepth(); - } - - public Long getByteTotalEnqueues() - { - return _obj.getTotalEnqueueSize(); - } - - public Long getByteTotalDequeues() - { - return _obj.getTotalDequeueSize(); - } - - public Long getByteTxnEnqueues() - { - return _obj.getByteTxnEnqueues(); - } - - public Long getByteTxnDequeues() - { - return _obj.getByteTxnDequeues(); - } - - public Long getBytePersistEnqueues() - { - return _obj.getPersistentByteEnqueues(); - } - - public Long getBytePersistDequeues() - { - return _obj.getPersistentByteDequeues(); - } - - public Long getMsgFtdEnqueues() - { - // TODO - return 0L; - } - - public Long getMsgFtdDequeues() - { - // TODO - return 0L; - } - - public Long getByteFtdEnqueues() - { - // TODO - return 0L; - } - - public Long getByteFtdDequeues() - { - // TODO - return 0L; - } - - public Long getMsgFtdDepth() - { - // TODO - return 0L; - } - - public Long getByteFtdDepth() - { - // TODO - return 0L; - } - - public Long getReleases() - { - // TODO - return 0L; - } - - public Long getAcquires() - { - // TODO - return 0L; - } - - public Long getDiscardsTtl() - { - // TODO - return 0L; - } - - public Long getDiscardsRing() - { - // TODO - return 0L; - } - - public Long getDiscardsLvq() - { - // TODO - return 0L; - } - - public Long getDiscardsOverflow() - { - // TODO - return 0L; - } - - public Long getDiscardsSubscriber() - { - // TODO - return 0L; - } - - public Long getDiscardsPurge() - { - // TODO - return 0L; - } - - public Long getReroutes() - { - // TODO - return 0L; - } - - public Long getConsumerCount() - { - return (long) _obj.getConsumerCount(); - } - - public Long getConsumerCountHigh() - { - return (long) _obj.getConsumerCountHigh(); - } - - public Long getConsumerCountLow() - { - // TODO - return 0l; - } - - public Long getBindingCount() - { - return (long) _obj.getBindingCount(); - } - - public Long getBindingCountHigh() - { - return (long) _obj.getBindingCountHigh(); - } - - public Long getBindingCountLow() - { - // TODO - return 0l; - } - - public Long getUnackedMessages() - { - return _obj.getUnackedMessageCount(); - } - - public Long getUnackedMessagesHigh() - { - return _obj.getUnackedMessageCountHigh(); - } - - public Long getUnackedMessagesLow() - { - // TODO - return 0l; - } - - public Long getMessageLatencySamples() - { - // TODO - return 0l; - } - - public Long getMessageLatencyMin() - { - // TODO - return 0l; - } - - public Long getMessageLatencyMax() - { - // TODO - return 0l; - } - - public Long getMessageLatencyAverage() - { - // TODO - return 0l; - } - - public Boolean getFlowStopped() - { - return Boolean.FALSE; - } - - public Long getFlowStoppedCount() - { - return 0L; - } - - public BrokerSchema.QueueClass.PurgeMethodResponseCommand purge(final BrokerSchema.QueueClass.PurgeMethodResponseCommandFactory factory, - final Long request, - final Map filter) // TODO: support for purge-by-group-identifier - { - try - { - _obj.purge(request); - } catch (AMQException e) - { - // TODO - throw new RuntimeException(); - } - return factory.createResponseCommand(); - } - - public BrokerSchema.QueueClass.RerouteMethodResponseCommand reroute(final BrokerSchema.QueueClass.RerouteMethodResponseCommandFactory factory, - final Long request, - final Boolean useAltExchange, - final String exchange, - final Map filter) // TODO: support for re-route-by-group-identifier - { - //TODO - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - - public Map getArguments() - { - return _obj.getArguments(); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public String toString() - { - return _obj.toString(); - } - } - - private class BindingDelegate implements BrokerSchema.BindingDelegate - { - private final BindingConfig _obj; - - public BindingDelegate(final BindingConfig obj) - { - _obj = obj; - } - - public BrokerSchema.ExchangeObject getExchangeRef() - { - return (BrokerSchema.ExchangeObject) adapt(_obj.getExchange()); - } - - public BrokerSchema.QueueObject getQueueRef() - { - return (BrokerSchema.QueueObject) adapt(_obj.getQueue()); - } - - public String getBindingKey() - { - return _obj.getBindingKey(); - } - - public Map getArguments() - { - return _obj.getArguments(); - } - - public String getOrigin() - { - return _obj.getOrigin(); - } - - public Long getMsgMatched() - { - // TODO - return _obj.getMatches(); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public String toString() - { - return _obj.toString(); - } - } - - private class ConnectionDelegate implements BrokerSchema.ConnectionDelegate - { - private final ConnectionConfig _obj; - - public ConnectionDelegate(final ConnectionConfig obj) - { - _obj = obj; - } - - public BrokerSchema.VhostObject getVhostRef() - { - return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); - } - - public String getAddress() - { - return _obj.getAddress(); - } - - public Boolean getIncoming() - { - return _obj.isIncoming(); - } - - public Boolean getSystemConnection() - { - return _obj.isSystemConnection(); - } - - public Boolean getFederationLink() - { - return _obj.isFederationLink(); - } - - public String getAuthIdentity() - { - return _obj.getAuthId(); - } - - public String getRemoteProcessName() - { - return _obj.getRemoteProcessName(); - } - - public Long getRemotePid() - { - Integer remotePID = _obj.getRemotePID(); - return remotePID == null ? null : (long) remotePID; - } - - public Long getRemoteParentPid() - { - Integer remotePPID = _obj.getRemoteParentPID(); - return remotePPID == null ? null : (long) remotePPID; - - } - - public Boolean getClosing() - { - return false; - } - - public Long getFramesFromClient() - { - // TODO - return 0l; - } - - public Long getFramesToClient() - { - // TODO - return 0l; - } - - public Long getBytesFromClient() - { - // TODO - return 0l; - } - - public Long getBytesToClient() - { - // TODO - return 0l; - } - - public Long getMsgsFromClient() - { - // TODO - return 0l; - } - - public Long getMsgsToClient() - { - // TODO - return 0l; - } - - public BrokerSchema.ConnectionClass.CloseMethodResponseCommand close(final BrokerSchema.ConnectionClass.CloseMethodResponseCommandFactory factory) - { - _obj.mgmtClose(); - - return factory.createResponseCommand(); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public Boolean getShadow() - { - return _obj.isShadow(); - } - - public Boolean getUserProxyAuth() - { - // TODO - return false; - } - - public String getSaslMechanism() - { - // TODO - return null; - } - public Integer getSaslSsf() - { - // TODO - return 0; - } - - - public String toString() - { - return _obj.toString(); - } - } - - private class SessionDelegate implements BrokerSchema.SessionDelegate - { - private final SessionConfig _obj; - - public SessionDelegate(final SessionConfig obj) - { - _obj = obj; - } - - public BrokerSchema.VhostObject getVhostRef() - { - return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); - } - - public String getName() - { - return _obj.getSessionName(); - } - - public Integer getChannelId() - { - return _obj.getChannel(); - } - - public BrokerSchema.ConnectionObject getConnectionRef() - { - return (BrokerSchema.ConnectionObject) adapt(_obj.getConnectionConfig()); - } - - public Long getDetachedLifespan() - { - return _obj.getDetachedLifespan(); - } - - public Boolean getAttached() - { - return _obj.isAttached(); - } - - public Long getExpireTime() - { - return _obj.getExpiryTime(); - } - - public Long getMaxClientRate() - { - return _obj.getMaxClientRate(); - } - - public Long getFramesOutstanding() - { - // TODO - return 0l; - } - - public Long getUnackedMessages() - { - // TODO - return 0l; - } - - public Long getTxnStarts() - { - return _obj.getTxnStarts(); - } - - public Long getTxnCommits() - { - return _obj.getTxnCommits(); - } - - public Long getTxnRejects() - { - return _obj.getTxnRejects(); - } - - public Long getTxnCount() - { - return _obj.getTxnCount(); - } - - public Long getClientCredit() - { - // TODO - return 0l; - } - - public BrokerSchema.SessionClass.SolicitAckMethodResponseCommand solicitAck(final BrokerSchema.SessionClass.SolicitAckMethodResponseCommandFactory factory) - { - //TODO - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.SessionClass.DetachMethodResponseCommand detach(final BrokerSchema.SessionClass.DetachMethodResponseCommandFactory factory) - { - //TODO - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.SessionClass.ResetLifespanMethodResponseCommand resetLifespan(final BrokerSchema.SessionClass.ResetLifespanMethodResponseCommandFactory factory) - { - //TODO - return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); - } - - public BrokerSchema.SessionClass.CloseMethodResponseCommand close(final BrokerSchema.SessionClass.CloseMethodResponseCommandFactory factory) - { - try - { - _obj.mgmtClose(); - } - catch (AMQException e) - { - return factory.createResponseCommand(CompletionCode.EXCEPTION, e.getMessage()); - } - - return factory.createResponseCommand(); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public String toString() - { - return _obj.toString(); - } - } - - private class SubscriptionDelegate implements BrokerSchema.SubscriptionDelegate - { - private final SubscriptionConfig _obj; - - private SubscriptionDelegate(final SubscriptionConfig obj) - { - _obj = obj; - } - - - public BrokerSchema.SessionObject getSessionRef() - { - return (BrokerSchema.SessionObject) adapt(_obj.getSessionConfig()); - } - - public BrokerSchema.QueueObject getQueueRef() - { - return (BrokerSchema.QueueObject) adapt(_obj.getQueue()); - } - - public String getName() - { - return _obj.getName(); - } - - public Boolean getBrowsing() - { - return _obj.isBrowsing(); - } - - public Boolean getAcknowledged() - { - return _obj.isExplicitAcknowledge(); - } - - public Boolean getExclusive() - { - return _obj.isExclusive(); - } - - public String getCreditMode() - { - return _obj.getCreditMode(); - } - - public Map getArguments() - { - return _obj.getArguments(); - } - - public Long getDelivered() - { - return _obj.getDelivered(); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public String toString() - { - return _obj.toString(); - } - } - - private class BridgeDelegate implements BrokerSchema.BridgeDelegate - { - private final BridgeConfig _obj; - - private BridgeDelegate(final BridgeConfig obj) - { - _obj = obj; - } - - public BrokerSchema.LinkObject getLinkRef() - { - return (BrokerSchema.LinkObject) adapt(_obj.getLink()); - } - - public Integer getChannelId() - { - return _obj.getChannelId(); - } - - public Boolean getDurable() - { - return _obj.isDurable(); - } - - public String getSrc() - { - return _obj.getSource(); - } - - public String getDest() - { - return _obj.getDestination(); - } - - public String getKey() - { - return _obj.getKey(); - } - - public Boolean getSrcIsQueue() - { - return _obj.isQueueBridge(); - } - - public Boolean getSrcIsLocal() - { - return _obj.isLocalSource(); - } - - public String getTag() - { - return _obj.getTag(); - } - - public String getExcludes() - { - return _obj.getExcludes(); - } - - public Boolean getDynamic() - { - return _obj.isDynamic(); - } - - public Integer getSync() - { - return _obj.getAckBatching(); - } - - /* support TBD */ - public String getName() - { - return null; - } - - public BrokerSchema.BridgeClass.CloseMethodResponseCommand close(final BrokerSchema.BridgeClass.CloseMethodResponseCommandFactory factory) - { - return null; - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - public String toString() - { - return _obj.toString(); - } - } - - private class LinkDelegate implements BrokerSchema.LinkDelegate - { - private final LinkConfig _obj; - - private LinkDelegate(final LinkConfig obj) - { - _obj = obj; - } - - public BrokerSchema.VhostObject getVhostRef() - { - return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); - } - - public String getHost() - { - return _obj.getHost(); - } - - public Integer getPort() - { - return _obj.getPort(); - } - - public String getTransport() - { - return _obj.getTransport(); - } - - public Boolean getDurable() - { - return _obj.isDurable(); - } - - public String getState() - { - return _obj.getState(); - } - - public String getLastError() - { - return _obj.getLastError(); - } - - /* support TBD */ - public String getName() - { - return null; - } - - /* support TBD */ - public BrokerSchema.ConnectionObject getConnectionRef() - { - return (BrokerSchema.ConnectionObject) null; - } - - public BrokerSchema.LinkClass.CloseMethodResponseCommand close(final BrokerSchema.LinkClass.CloseMethodResponseCommandFactory factory) - { - _obj.close(); - return factory.createResponseCommand(); - } - - public BrokerSchema.LinkClass.BridgeMethodResponseCommand bridge(final BrokerSchema.LinkClass.BridgeMethodResponseCommandFactory factory, - final Boolean durable, - final String src, - final String dest, - final String key, - final String tag, - final String excludes, - final Boolean srcIsQueue, - final Boolean srcIsLocal, - final Boolean dynamic, - final Integer sync) - { - _obj.createBridge(durable, dynamic, srcIsQueue, srcIsLocal, src, dest, key, tag, excludes); - return factory.createResponseCommand(); - } - - public UUID getQMFId() - { - return _obj.getQMFId(); - } - - public long getCreateTime() - { - return _obj.getCreateTime(); - } - - @Override - public String toString() - { - return _obj.toString(); - } - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFStatistic.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFStatistic.java deleted file mode 100644 index 89d650e03b..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFStatistic.java +++ /dev/null @@ -1,61 +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.qmf; - -import org.apache.qpid.transport.codec.Encoder; - -import java.util.LinkedHashMap; - -public class QMFStatistic -{ - private final LinkedHashMap _map = new LinkedHashMap(); - private static final String NAME = "name"; - private static final String TYPE = "type"; - private static final String UNIT = "unit"; - private static final String DESCRIPTION = "desc"; - - - public QMFStatistic(String name, QMFType type, String unit, String description) - { - _map.put(NAME, name); - _map.put(TYPE, type.codeValue()); - if(unit != null) - { - _map.put(UNIT, unit); - } - if(description != null) - { - _map.put(DESCRIPTION, description); - } - - } - - public void encode(Encoder encoder) - { - encoder.writeMap(_map); - } - - public String getName() - { - return (String) _map.get(NAME); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFType.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFType.java deleted file mode 100644 index 0e01c27db5..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFType.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.qmf; - -public enum QMFType -{ - - UINT8, - UINT16, - UINT32, - UINT64, - UNKNOWN, - STR8, - STR16, - ABSTIME, - DELTATIME, - OBJECTREFERENCE, - BOOLEAN, - FLOAT, - DOUBLE, - UUID, - MAP, - INT8, - INT16, - INT32, - INT64, - OBJECT, - LIST, - ARRAY; - - public int codeValue() - { - return ordinal()+1; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java index e197dddfde..ab4ca81d05 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java +++ b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java @@ -51,13 +51,10 @@ import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction; import org.apache.qpid.server.ack.UnacknowledgedMessageMap; import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.ConnectionConfig; -import org.apache.qpid.server.configuration.SessionConfig; -import org.apache.qpid.server.configuration.SessionConfigType; +import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.flow.FlowCreditManager; import org.apache.qpid.server.flow.Pre0_10CreditManager; @@ -75,7 +72,6 @@ import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.protocol.AMQProtocolEngine; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; @@ -83,7 +79,6 @@ import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.InboundMessageAdapter; import org.apache.qpid.server.queue.IncomingMessage; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.StoreFuture; import org.apache.qpid.server.store.StoredMessage; @@ -93,19 +88,19 @@ import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; import org.apache.qpid.server.txn.AsyncAutoCommitTransaction; import org.apache.qpid.server.txn.LocalTransaction; +import org.apache.qpid.server.txn.LocalTransaction.ActivityTimeAccessor; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.TransportException; -public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoCommitTransaction.FutureRecorder +public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.FutureRecorder { public static final int DEFAULT_PREFETCH = 4096; private static final Logger _logger = Logger.getLogger(AMQChannel.class); - private static final boolean MSG_AUTH = - ApplicationRegistry.getInstance().getConfiguration().getMsgAuth(); - + //TODO use Broker property to configure message authorization requirements + private boolean _messageAuthorizationRequired = Boolean.getBoolean(BrokerProperties.PROPERTY_MSG_AUTH); private final int _channelId; @@ -118,7 +113,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm */ private long _deliveryTag = 0; - /** A channel has a default queue (the last declared) that is used when no queue name is explictily set */ + /** A channel has a default queue (the last declared) that is used when no queue name is explicitly set */ private AMQQueue _defaultQueue; /** This tag is unique per subscription to a queue. The server returns this in response to a basic.consume request. */ @@ -151,7 +146,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm private final AtomicLong _txnCommits = new AtomicLong(0); private final AtomicLong _txnRejects = new AtomicLong(0); private final AtomicLong _txnCount = new AtomicLong(0); - private final AtomicLong _txnUpdateTime = new AtomicLong(0); private final AMQProtocolSession _session; private AtomicBoolean _closing = new AtomicBoolean(false); @@ -169,12 +163,12 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm private List _resendList = new ArrayList(); private static final AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible."); - private final UUID _qmfId; private long _createTime = System.currentTimeMillis(); private final ClientDeliveryMethod _clientDeliveryMethod; private final TransactionTimeoutHelper _transactionTimeoutHelper; + private final UUID _id = UUID.randomUUID(); public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore) throws AMQException @@ -184,30 +178,36 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm _actor = new AMQPChannelActor(this, session.getLogActor().getRootMessageLogger()); _logSubject = new ChannelLogSubject(this); - _qmfId = getConfigStore().createId(); _actor.message(ChannelMessages.CREATE()); - getConfigStore().addConfiguredObject(this); - _messageStore = messageStore; // by default the session is non-transactional _transaction = new AsyncAutoCommitTransaction(_messageStore, this); - _clientDeliveryMethod = session.createDeliveryMethod(_channelId); - - _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject); - } + _clientDeliveryMethod = session.createDeliveryMethod(_channelId); - public ConfigStore getConfigStore() - { - return getVirtualHost().getConfigStore(); + _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject, new CloseAction() + { + @Override + public void doTimeoutAction(String reason) throws AMQException + { + closeConnection(reason); + } + }); } /** Sets this channel to be part of a local transaction */ public void setLocalTransactional() { - _transaction = new LocalTransaction(_messageStore); + _transaction = new LocalTransaction(_messageStore, new ActivityTimeAccessor() + { + @Override + public long getActivityTime() + { + return _session.getLastReceivedTime(); + } + }); _txnStarts.incrementAndGet(); } @@ -221,12 +221,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm sync(); } - - public boolean inTransaction() - { - return isTransactional() && _txnUpdateTime.get() > 0 && _transaction.getTransactionStartTime() > 0; - } - private void incrementOutstandingTxnsIfNecessary() { if(isTransactional()) @@ -247,11 +241,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm } } - public Long getTxnStarts() - { - return _txnStarts.get(); - } - public Long getTxnCommits() { return _txnCommits.get(); @@ -369,9 +358,8 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm } }); - _transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues), getProtocolSession().getLastReceivedTime()); + _transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues)); incrementOutstandingTxnsIfNecessary(); - updateTransactionalActivity(); _currentMessage.getStoredMessage().flushToStore(); } } @@ -396,7 +384,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm if (_logger.isDebugEnabled()) { - _logger.debug(debugIdentity() + "Content body received on channel " + _channelId); + _logger.debug(debugIdentity() + " content body received on channel " + _channelId); } try @@ -556,9 +544,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm { _logger.error("Caught TransportException whilst attempting to requeue:" + e); } - - getConfigStore().removeConfiguredObject(this); - } private void unsubscribeAllConsumers() throws AMQException @@ -860,7 +845,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm { Collection ackedMessages = getAckedMessages(deliveryTag, multiple); _transaction.dequeue(ackedMessages, new MessageAcknowledgeAction(ackedMessages)); - updateTransactionalActivity(); } private Collection getAckedMessages(long deliveryTag, boolean multiple) @@ -1054,19 +1038,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm } } - - - } - - /** - * Update last transaction activity timestamp - */ - private void updateTransactionalActivity() - { - if (isTransactional()) - { - _txnUpdateTime.set(getProtocolSession().getLastReceivedTime()); - } } public String toString() @@ -1149,10 +1120,16 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm ? ((BasicContentHeaderProperties) header.getProperties()).getUserId() : null; - return (!MSG_AUTH || _session.getAuthorizedPrincipal().getName().equals(userID == null? "" : userID.toString())); + return (!_messageAuthorizationRequired || _session.getAuthorizedPrincipal().getName().equals(userID == null? "" : userID.toString())); } + @Override + public UUID getId() + { + return _id; + } + public AMQConnectionModel getConnectionModel() { return _session; @@ -1168,6 +1145,12 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm return _logSubject; } + @Override + public int compareTo(AMQSessionModel o) + { + return getId().compareTo(o.getId()); + } + private class MessageDeliveryAction implements ServerTransaction.Action { private IncomingMessage _incommingMessage; @@ -1221,11 +1204,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm // TODO throw new RuntimeException(e); } - - - - - } public void onRollback() @@ -1375,7 +1353,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm public void onRollback() { - //To change body of implemented methods use File | Settings | File Templates. } } @@ -1469,97 +1446,24 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm return getProtocolSession().getVirtualHost(); } - - public ConfiguredObject getParent() - { - return getVirtualHost(); - } - - public SessionConfigType getConfigType() - { - return SessionConfigType.getInstance(); - } - public int getChannel() { return getChannelId(); } - public boolean isAttached() - { - return true; - } - - public long getDetachedLifespan() - { - return 0; - } - - public ConnectionConfig getConnectionConfig() - { - return (AMQProtocolEngine)getProtocolSession(); - } - - public Long getExpiryTime() - { - return null; - } - - public Long getMaxClientRate() - { - return null; - } - public boolean isDurable() { return false; } - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public String getSessionName() - { - return getConnectionConfig().getAddress() + "/" + getChannelId(); - } - public long getCreateTime() { return _createTime; } - public void mgmtClose() throws AMQException - { - _session.mgmtCloseChannel(_channelId); - } - public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException { - if (inTransaction()) - { - long currentTime = System.currentTimeMillis(); - long openTime = currentTime - _transaction.getTransactionStartTime(); - long idleTime = currentTime - _txnUpdateTime.get(); - - _transactionTimeoutHelper.logIfNecessary(idleTime, idleWarn, ChannelMessages.IDLE_TXN(idleTime), - TransactionTimeoutHelper.IDLE_TRANSACTION_ALERT); - if (_transactionTimeoutHelper.isTimedOut(idleTime, idleClose)) - { - closeConnection("Idle transaction timed out"); - return; - } - - _transactionTimeoutHelper.logIfNecessary(openTime, openWarn, ChannelMessages.OPEN_TXN(openTime), - TransactionTimeoutHelper.OPEN_TRANSACTION_ALERT); - if (_transactionTimeoutHelper.isTimedOut(openTime, openClose)) - { - closeConnection("Open transaction timed out"); - return; - } - } + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, openWarn, openClose, idleWarn, idleClose); } /** @@ -1637,6 +1541,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm public void sync() { + if(_logger.isDebugEnabled()) + { + _logger.debug("sync() called on channel " + debugIdentity()); + } + AsyncCommand cmd; while((cmd = _unfinishedCommandsQueue.poll()) != null) { @@ -1674,16 +1583,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm _action.postCommit(); _action = null; } - - boolean isReadyForCompletion() - { - return _future.isComplete(); - } - } - - public int compareTo(AMQSessionModel session) - { - return getQMFId().compareTo(session.getQMFId()); } @Override diff --git a/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/java/broker/src/main/java/org/apache/qpid/server/Broker.java index d58a0d5bb4..54dcf0543d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/Broker.java +++ b/java/broker/src/main/java/org/apache/qpid/server/Broker.java @@ -23,37 +23,31 @@ package org.apache.qpid.server; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.*; -import javax.net.ssl.SSLContext; +import java.util.List; +import java.util.Properties; +import java.util.Set; + import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.configuration.ServerNetworkTransportConfiguration; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.BrokerConfigurationStoreCreator; +import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler; import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.GenericActor; -import org.apache.qpid.server.logging.log4j.LoggingFacade; +import org.apache.qpid.server.logging.log4j.LoggingManagementFacade; import org.apache.qpid.server.logging.messages.BrokerMessages; -import org.apache.qpid.server.protocol.AmqpProtocolVersion; -import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; -import org.apache.qpid.server.transport.QpidAcceptor; -import org.apache.qpid.ssl.SSLContextFactory; -import org.apache.qpid.transport.NetworkTransportConfiguration; -import org.apache.qpid.transport.network.IncomingNetworkTransport; -import org.apache.qpid.transport.network.Transport; - -import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; +import org.apache.qpid.server.registry.IApplicationRegistry; public class Broker { private static final Logger LOGGER = Logger.getLogger(Broker.class); private volatile Thread _shutdownHookThread; + private volatile IApplicationRegistry _applicationRegistry; protected static class InitException extends RuntimeException { @@ -73,7 +67,17 @@ public class Broker } finally { - ApplicationRegistry.remove(); + try + { + if (_applicationRegistry != null) + { + _applicationRegistry.close(); + } + } + finally + { + clearAMQShortStringCache(); + } } } @@ -84,274 +88,76 @@ public class Broker public void startup(final BrokerOptions options) throws Exception { + CurrentActor.set(new BrokerActor(new SystemOutMessageLogger())); try { - CurrentActor.set(new BrokerActor(new SystemOutMessageLogger())); startupImpl(options); addShutdownHook(); } finally { - CurrentActor.remove(); + try + { + CurrentActor.remove(); + } + finally + { + clearAMQShortStringCache(); + } } } private void startupImpl(final BrokerOptions options) throws Exception { - final String qpidHome = options.getQpidHome(); - final File configFile = getConfigFile(options.getConfigFile(), - BrokerOptions.DEFAULT_CONFIG_FILE, qpidHome, true); - - CurrentActor.get().message(BrokerMessages.CONFIG(configFile.getAbsolutePath())); - - File logConfigFile = getConfigFile(options.getLogConfigFile(), - BrokerOptions.DEFAULT_LOG_CONFIG_FILE, qpidHome, false); - - configureLogging(logConfigFile, options.getLogWatchFrequency()); + final String qpidHome = System.getProperty(BrokerProperties.PROPERTY_QPID_HOME); + String storeLocation = options.getConfigurationStoreLocation(); + String storeType = options.getConfigurationStoreType(); - ConfigurationFileApplicationRegistry config = new ConfigurationFileApplicationRegistry(configFile, options.getBundleContext()); - ServerConfiguration serverConfig = config.getConfiguration(); - if (options.getQpidWork() != null) + if (storeLocation == null) { - serverConfig.setQpidWork(options.getQpidWork()); - } - if (options.getQpidHome() != null) - { - serverConfig.setQpidHome(options.getQpidHome()); - } - updateManagementPorts(serverConfig, options.getJmxPortRegistryServer(), options.getJmxPortConnectorServer()); - - ApplicationRegistry.initialise(config); - - // We have already loaded the BrokerMessages class by this point so we - // need to refresh the locale setting incase we had a different value in - // the configuration. - BrokerMessages.reload(); - - // AR.initialise() sets and removes its own actor so we now need to set the actor - // for the remainder of the startup, and the default actor if the stack is empty - CurrentActor.set(new BrokerActor(config.getCompositeStartupMessageLogger())); - CurrentActor.setDefault(new BrokerActor(config.getRootMessageLogger())); - GenericActor.setDefaultMessageLogger(config.getRootMessageLogger()); - - try - { - Set ports = new HashSet(options.getPorts()); - if(ports.isEmpty()) - { - parsePortList(ports, serverConfig.getPorts()); - } - - Set sslPorts = new HashSet(options.getSSLPorts()); - if(sslPorts.isEmpty()) - { - parsePortList(sslPorts, serverConfig.getSSLPorts()); - } - - //1-0 excludes and includes - Set exclude_1_0 = new HashSet(options.getExcludedPorts(ProtocolExclusion.v1_0)); - if(exclude_1_0.isEmpty()) - { - parsePortList(exclude_1_0, serverConfig.getPortExclude10()); - } - - Set include_1_0 = new HashSet(options.getIncludedPorts(ProtocolInclusion.v1_0)); - if(include_1_0.isEmpty()) - { - parsePortList(include_1_0, serverConfig.getPortInclude10()); - } - - //0-10 excludes and includes - Set exclude_0_10 = new HashSet(options.getExcludedPorts(ProtocolExclusion.v0_10)); - if(exclude_0_10.isEmpty()) - { - parsePortList(exclude_0_10, serverConfig.getPortExclude010()); - } - - Set include_0_10 = new HashSet(options.getIncludedPorts(ProtocolInclusion.v0_10)); - if(include_0_10.isEmpty()) - { - parsePortList(include_0_10, serverConfig.getPortInclude010()); - } - - //0-9-1 excludes and includes - Set exclude_0_9_1 = new HashSet(options.getExcludedPorts(ProtocolExclusion.v0_9_1)); - if(exclude_0_9_1.isEmpty()) - { - parsePortList(exclude_0_9_1, serverConfig.getPortExclude091()); - } - - Set include_0_9_1 = new HashSet(options.getIncludedPorts(ProtocolInclusion.v0_9_1)); - if(include_0_9_1.isEmpty()) - { - parsePortList(include_0_9_1, serverConfig.getPortInclude091()); - } - - //0-9 excludes and includes - Set exclude_0_9 = new HashSet(options.getExcludedPorts(ProtocolExclusion.v0_9)); - if(exclude_0_9.isEmpty()) - { - parsePortList(exclude_0_9, serverConfig.getPortExclude09()); - } - - Set include_0_9 = new HashSet(options.getIncludedPorts(ProtocolInclusion.v0_9)); - if(include_0_9.isEmpty()) - { - parsePortList(include_0_9, serverConfig.getPortInclude09()); - } - - //0-8 excludes and includes - Set exclude_0_8 = new HashSet(options.getExcludedPorts(ProtocolExclusion.v0_8)); - if(exclude_0_8.isEmpty()) - { - parsePortList(exclude_0_8, serverConfig.getPortExclude08()); - } - - Set include_0_8 = new HashSet(options.getIncludedPorts(ProtocolInclusion.v0_8)); - if(include_0_8.isEmpty()) - { - parsePortList(include_0_8, serverConfig.getPortInclude08()); - } - - String bindAddr = options.getBind(); - if (bindAddr == null) - { - bindAddr = serverConfig.getBind(); - } - - InetAddress bindAddress; - if (bindAddr.equals(WILDCARD_ADDRESS)) - { - bindAddress = null; - } - else - { - bindAddress = InetAddress.getByName(bindAddr); - } - - final AmqpProtocolVersion defaultSupportedProtocolReply = serverConfig.getDefaultSupportedProtocolReply(); - - if (!serverConfig.getSSLOnly()) - { - for(int port : ports) - { - final InetSocketAddress inetSocketAddress = new InetSocketAddress(bindAddress, port); - - final Set supported = - getSupportedVersions(port, exclude_1_0, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8, - include_1_0, include_0_10, include_0_9_1, include_0_9, include_0_8,serverConfig); - - final NetworkTransportConfiguration settings = - new ServerNetworkTransportConfiguration(serverConfig, inetSocketAddress, Transport.TCP); - - final IncomingNetworkTransport transport = Transport.getIncomingTransportInstance(); - final MultiVersionProtocolEngineFactory protocolEngineFactory = - new MultiVersionProtocolEngineFactory(supported, defaultSupportedProtocolReply); - - transport.accept(settings, protocolEngineFactory, null); - - ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress, - new QpidAcceptor(transport,QpidAcceptor.Transport.TCP, supported)); - CurrentActor.get().message(BrokerMessages.LISTENING("TCP", port)); - } - } - - if (serverConfig.getEnableSSL()) + String qpidWork = System.getProperty(BrokerProperties.PROPERTY_QPID_WORK); + if (qpidWork == null) { - final String keystorePath = serverConfig.getConnectorKeyStorePath(); - final String keystorePassword = serverConfig.getConnectorKeyStorePassword(); - final String keystoreType = serverConfig.getConnectorKeyStoreType(); - final String keyManagerFactoryAlgorithm = serverConfig.getConnectorKeyManagerFactoryAlgorithm(); - final SSLContext sslContext; - if(serverConfig.getConnectorTrustStorePath()!=null) - { - sslContext = SSLContextFactory.buildClientContext(serverConfig.getConnectorTrustStorePath(), - serverConfig.getConnectorTrustStorePassword(), - serverConfig.getConnectorTrustStoreType(), - serverConfig.getConnectorTrustManagerFactoryAlgorithm(), - keystorePath, - keystorePassword, keystoreType, keyManagerFactoryAlgorithm, - serverConfig.getCertAlias()); - } - else - { - sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keystoreType, keyManagerFactoryAlgorithm); - } - - for(int sslPort : sslPorts) - { - final InetSocketAddress inetSocketAddress = new InetSocketAddress(bindAddress, sslPort); - - final Set supported = - getSupportedVersions(sslPort, exclude_1_0, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8, - include_1_0, include_0_10, include_0_9_1, include_0_9, include_0_8, serverConfig); - final NetworkTransportConfiguration settings = - new ServerNetworkTransportConfiguration(serverConfig, inetSocketAddress, Transport.TCP); - - final IncomingNetworkTransport transport = Transport.getIncomingTransportInstance(); - final MultiVersionProtocolEngineFactory protocolEngineFactory = - new MultiVersionProtocolEngineFactory(supported, defaultSupportedProtocolReply); - - transport.accept(settings, protocolEngineFactory, sslContext); - - ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress, - new QpidAcceptor(transport,QpidAcceptor.Transport.SSL, supported)); - CurrentActor.get().message(BrokerMessages.LISTENING("TCP/SSL", sslPort)); - } + qpidWork = new File(System.getProperty("user.dir"), "work").getAbsolutePath(); } - - CurrentActor.get().message(BrokerMessages.READY()); - } - finally - { - // Startup is complete so remove the AR initialised Startup actor - CurrentActor.remove(); + storeLocation = new File(qpidWork, BrokerOptions.DEFAULT_CONFIG_FILE + "." + storeType).getAbsolutePath(); } - } - private static Set getSupportedVersions(final int port, - final Set exclude_1_0, - final Set exclude_0_10, - final Set exclude_0_9_1, - final Set exclude_0_9, - final Set exclude_0_8, - final Set include_1_0, - final Set include_0_10, - final Set include_0_9_1, - final Set include_0_9, - final Set include_0_8, - final ServerConfiguration serverConfig) - { - final EnumSet supported = EnumSet.allOf(AmqpProtocolVersion.class); + CurrentActor.get().message(BrokerMessages.CONFIG(storeLocation)); - if((exclude_1_0.contains(port) || !serverConfig.isAmqp10enabled()) && !include_1_0.contains(port)) - { - supported.remove(AmqpProtocolVersion.v1_0_0); - } + File logConfigFile = getConfigFile(options.getLogConfigFile(), BrokerOptions.DEFAULT_LOG_CONFIG_FILE, qpidHome, false); + configureLogging(logConfigFile, options.getLogWatchFrequency()); - if((exclude_0_10.contains(port) || !serverConfig.isAmqp010enabled()) && !include_0_10.contains(port)) - { - supported.remove(AmqpProtocolVersion.v0_10); - } + BrokerConfigurationStoreCreator storeCreator = new BrokerConfigurationStoreCreator(); + ConfigurationEntryStore store = storeCreator.createStore(storeLocation, storeType, + options.getInitialConfigurationStoreLocation(), options.getInitialConfigurationStoreLocation()); - if((exclude_0_9_1.contains(port) || !serverConfig.isAmqp091enabled()) && !include_0_9_1.contains(port)) + if (options.isManagementMode()) { - supported.remove(AmqpProtocolVersion.v0_9_1); + store = new ManagementModeStoreHandler(store, options); } - if((exclude_0_9.contains(port) || !serverConfig.isAmqp09enabled()) && !include_0_9.contains(port)) + _applicationRegistry = new ApplicationRegistry(store); + try { - supported.remove(AmqpProtocolVersion.v0_9); + _applicationRegistry.initialise(); } - - if((exclude_0_8.contains(port) || !serverConfig.isAmqp08enabled()) && !include_0_8.contains(port)) + catch(Exception e) { - supported.remove(AmqpProtocolVersion.v0_8); + try + { + _applicationRegistry.close(); + } + catch(Exception ce) + { + LOGGER.debug("An error occured when closing the registry following initialization failure", ce); + } + throw e; } - return supported; } + private File getConfigFile(final String fileName, final String defaultFileName, final String qpidHome, boolean throwOnFileNotFound) throws InitException @@ -368,11 +174,11 @@ public class Broker if (!configFile.exists() && throwOnFileNotFound) { - String error = "File " + fileName + " could not be found. Check the file exists and is readable."; + String error = "File " + configFile + " could not be found. Check the file exists and is readable."; if (qpidHome == null) { - error = error + "\nNote: " + BrokerOptions.QPID_HOME + " is not set."; + error = error + "\nNote: " + BrokerProperties.PROPERTY_QPID_HOME + " is not set."; } throw new InitException(error, null); @@ -399,37 +205,6 @@ public class Broker } } - /** - * Update the configuration data with the management port. - * @param configuration - * @param registryServerPort The string from the command line - */ - private void updateManagementPorts(ServerConfiguration configuration, Integer registryServerPort, Integer connectorServerPort) - { - if (registryServerPort != null) - { - try - { - configuration.setJMXPortRegistryServer(registryServerPort); - } - catch (NumberFormatException e) - { - throw new InitException("Invalid management (registry server) port: " + registryServerPort, null); - } - } - if (connectorServerPort != null) - { - try - { - configuration.setJMXPortConnectorServer(connectorServerPort); - } - catch (NumberFormatException e) - { - throw new InitException("Invalid management (connector server) port: " + connectorServerPort, null); - } - } - } - private void configureLogging(File logConfigFile, int logWatchTime) throws InitException, IOException { if (logConfigFile.exists() && logConfigFile.canRead()) @@ -443,7 +218,7 @@ public class Broker // log4j expects the watch interval in milliseconds try { - LoggingFacade.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000); + LoggingManagementFacade.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000); } catch (Exception e) { @@ -454,7 +229,7 @@ public class Broker { try { - LoggingFacade.configure(logConfigFile.getPath()); + LoggingManagementFacade.configure(logConfigFile.getPath()); } catch (Exception e) { @@ -531,6 +306,24 @@ public class Broker LOGGER.debug("Skipping shutdown hook removal as there either isnt one, or we are it."); } } + /** + * Workaround that prevents AMQShortStrings cache from being left in the thread local. This is important + * when embedding the Broker in containers where the starting thread may not belong to Qpid. + * The long term solution here is to stop our use of AMQShortString outside the AMQP transport layer. + */ + private void clearAMQShortStringCache() + { + AMQShortString.clearLocalCache(); + } + + public org.apache.qpid.server.model.Broker getBroker() + { + if (_applicationRegistry == null) + { + return null; + } + return _applicationRegistry.getBroker(); + } private class ShutdownService implements Runnable { @@ -540,4 +333,5 @@ public class Broker Broker.this.shutdown(); } } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java b/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java index 434d40d557..57e401e608 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java +++ b/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java @@ -20,66 +20,25 @@ */ package org.apache.qpid.server; -import org.osgi.framework.BundleContext; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - public class BrokerOptions { - public static final String DEFAULT_CONFIG_FILE = "etc/config.xml"; + public static final String DEFAULT_STORE_TYPE = "json"; + public static final String DEFAULT_CONFIG_FILE = "config"; public static final String DEFAULT_LOG_CONFIG_FILE = "etc/log4j.xml"; - public static final String QPID_HOME = "QPID_HOME"; - public static final String QPID_WORK = "QPID_WORK"; - - private final Set _ports = new HashSet(); - private final Set _sslPorts = new HashSet(); - private final Map> _exclusionMap = new HashMap>(); - private final Map> _inclusionMap = new HashMap>(); - private String _configFile; private String _logConfigFile; - private String _bind; - private Integer _jmxPortRegistryServer; - private Integer _jmxPortConnectorServer; - private BundleContext _bundleContext; - private Integer _logWatchFrequency = 0; - private String _qpidWorkFolder; - private String _qpidHomeFolder; - public void addPort(final int port) - { - _ports.add(port); - } + private String _configurationStoreLocation; + private String _configurationStoreType = DEFAULT_STORE_TYPE; - public void addSSLPort(final int sslPort) - { - _sslPorts.add(sslPort); - } + private String _initialConfigurationStoreLocation; + private String _initialConfigurationStoreType = DEFAULT_STORE_TYPE; - public Set getPorts() - { - return Collections.unmodifiableSet(_ports); - } - - public Set getSSLPorts() - { - return Collections.unmodifiableSet(_sslPorts); - } - - public String getConfigFile() - { - return _configFile; - } - - public void setConfigFile(final String configFile) - { - _configFile = configFile; - } + private boolean _managementMode; + private int _managementModeRmiPort; + private int _managementModeConnectorPort; + private int _managementModeHttpPort; public String getLogConfigFile() { @@ -91,110 +50,97 @@ public class BrokerOptions _logConfigFile = logConfigFile; } - public Integer getJmxPortRegistryServer() + public int getLogWatchFrequency() { - return _jmxPortRegistryServer; + return _logWatchFrequency; } - public void setJmxPortRegistryServer(final int jmxPortRegistryServer) + /** + * Set the frequency with which the log config file will be checked for updates. + * @param logWatchFrequency frequency in seconds + */ + public void setLogWatchFrequency(final int logWatchFrequency) { - _jmxPortRegistryServer = jmxPortRegistryServer; + _logWatchFrequency = logWatchFrequency; } - public Integer getJmxPortConnectorServer() + public String getConfigurationStoreLocation() { - return _jmxPortConnectorServer; + return _configurationStoreLocation; } - public void setJmxPortConnectorServer(final int jmxPortConnectorServer) + public void setConfigurationStoreLocation(String cofigurationStore) { - _jmxPortConnectorServer = jmxPortConnectorServer; + _configurationStoreLocation = cofigurationStore; } - public String getQpidHome() + + public String getConfigurationStoreType() { - return _qpidHomeFolder == null? System.getProperty(QPID_HOME): _qpidHomeFolder; + return _configurationStoreType; } - public Set getExcludedPorts(final ProtocolExclusion excludeProtocol) + public void setConfigurationStoreType(String cofigurationStoreType) { - final Set excludedPorts = _exclusionMap.get(excludeProtocol); - return excludedPorts == null ? Collections.emptySet() : excludedPorts; + _configurationStoreType = cofigurationStoreType; } - public void addExcludedPort(final ProtocolExclusion excludeProtocol, final int port) + public void setInitialConfigurationStoreLocation(String initialConfigurationStore) { - if (!_exclusionMap.containsKey(excludeProtocol)) - { - _exclusionMap.put(excludeProtocol, new HashSet()); - } - - Set ports = _exclusionMap.get(excludeProtocol); - ports.add(port); + _initialConfigurationStoreLocation = initialConfigurationStore; } - public String getBind() + public void setInitialConfigurationStoreType(String initialConfigurationStoreType) { - return _bind; + _initialConfigurationStoreType = initialConfigurationStoreType; } - public void setBind(final String bind) + public String getInitialConfigurationStoreLocation() { - _bind = bind; + return _initialConfigurationStoreLocation; } - public int getLogWatchFrequency() + public String getInitialConfigurationStoreType() { - return _logWatchFrequency; + return _initialConfigurationStoreType; } - /** - * Set the frequency with which the log config file will be checked for updates. - * @param logWatchFrequency frequency in seconds - */ - public void setLogWatchFrequency(final int logWatchFrequency) + public boolean isManagementMode() { - _logWatchFrequency = logWatchFrequency; + return _managementMode; } - public BundleContext getBundleContext() + public void setManagementMode(boolean managementMode) { - return _bundleContext ; + _managementMode = managementMode; } - public void setBundleContext(final BundleContext bundleContext) + public int getManagementModeRmiPort() { - _bundleContext = bundleContext; + return _managementModeRmiPort; } - public Set getIncludedPorts(final ProtocolInclusion includeProtocol) + public void setManagementModeRmiPort(int managementModeRmiPort) { - final Set includedPorts = _inclusionMap.get(includeProtocol); - return includedPorts == null ? Collections.emptySet() : includedPorts; + _managementModeRmiPort = managementModeRmiPort; } - public void addIncludedPort(final ProtocolInclusion includeProtocol, final int port) + public int getManagementModeConnectorPort() { - if (!_inclusionMap.containsKey(includeProtocol)) - { - _inclusionMap.put(includeProtocol, new HashSet()); - } - - Set ports = _inclusionMap.get(includeProtocol); - ports.add(port); + return _managementModeConnectorPort; } - public String getQpidWork() + public void setManagementModeConnectorPort(int managementModeConnectorPort) { - return _qpidWorkFolder; + _managementModeConnectorPort = managementModeConnectorPort; } - public void setQpidWork(String qpidWorkFolder) + public int getManagementModeHttpPort() { - _qpidWorkFolder = qpidWorkFolder; + return _managementModeHttpPort; } - public void setQpidHome(String qpidHomeFolder) + public void setManagementModeHttpPort(int managementModeHttpPort) { - _qpidHomeFolder = qpidHomeFolder; + _managementModeHttpPort = managementModeHttpPort; } } \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/Main.java b/java/broker/src/main/java/org/apache/qpid/server/Main.java index 9fe7a6619f..4927956c6c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/Main.java +++ b/java/broker/src/main/java/org/apache/qpid/server/Main.java @@ -30,9 +30,6 @@ import org.apache.commons.cli.PosixParser; import org.apache.log4j.Logger; import org.apache.qpid.common.QpidProperties; import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.server.Broker.InitException; -import org.apache.qpid.server.registry.ApplicationRegistry; - /** * Main entry point for AMQPD. @@ -45,86 +42,17 @@ public class Main private static final Option OPTION_VERSION = new Option("v", "version", false, "print the version information and exit"); - private static final Option OPTION_CONFIG_FILE = - OptionBuilder.withArgName("file").hasArg().withDescription("use given configuration file").withLongOpt("config") - .create("c"); - - private static final Option OPTION_PORT = - OptionBuilder.withArgName("port").hasArg() - .withDescription("listen on the specified port. Overrides any value in the config file") - .withLongOpt("port").create("p"); - - private static final Option OPTION_SSLPORT = - OptionBuilder.withArgName("port").hasArg() - .withDescription("SSL port. Overrides any value in the config file") - .withLongOpt("sslport").create("s"); - - - private static final Option OPTION_EXCLUDE_1_0 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("when listening on the specified port do not accept AMQP1-0 connections. The specified port must be one specified on the command line") - .withLongOpt("exclude-1-0").create(); - - private static final Option OPTION_EXCLUDE_0_10 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("when listening on the specified port do not accept AMQP0-10 connections. The specified port must be one specified on the command line") - .withLongOpt("exclude-0-10").create(); - - private static final Option OPTION_EXCLUDE_0_9_1 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("when listening on the specified port do not accept AMQP0-9-1 connections. The specified port must be one specified on the command line") - .withLongOpt("exclude-0-9-1").create(); - - private static final Option OPTION_EXCLUDE_0_9 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("when listening on the specified port do not accept AMQP0-9 connections. The specified port must be one specified on the command line") - .withLongOpt("exclude-0-9").create(); - - private static final Option OPTION_EXCLUDE_0_8 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("when listening on the specified port do not accept AMQP0-8 connections. The specified port must be one specified on the command line") - .withLongOpt("exclude-0-8").create(); - - private static final Option OPTION_INCLUDE_1_0 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("accept AMQP1-0 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") - .withLongOpt("include-1-0").create(); - -private static final Option OPTION_INCLUDE_0_10 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("accept AMQP0-10 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") - .withLongOpt("include-0-10").create(); - -private static final Option OPTION_INCLUDE_0_9_1 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("accept AMQP0-9-1 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") - .withLongOpt("include-0-9-1").create(); - -private static final Option OPTION_INCLUDE_0_9 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("accept AMQP0-9 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") - .withLongOpt("include-0-9").create(); - -private static final Option OPTION_INCLUDE_0_8 = - OptionBuilder.withArgName("port").hasArg() - .withDescription("accept AMQP0-8 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") - .withLongOpt("include-0-8").create(); - - - private static final Option OPTION_JMX_PORT_REGISTRY_SERVER = - OptionBuilder.withArgName("port").hasArg() - .withDescription("listen on the specified management (registry server) port. Overrides any value in the config file") - .withLongOpt("jmxregistryport").create("m"); - - private static final Option OPTION_JMX_PORT_CONNECTOR_SERVER = - OptionBuilder.withArgName("port").hasArg() - .withDescription("listen on the specified management (connector server) port. Overrides any value in the config file") - .withLongOpt("jmxconnectorport").create(); - - private static final Option OPTION_BIND = - OptionBuilder.withArgName("address").hasArg() - .withDescription("bind to the specified address. Overrides any value in the config file") - .withLongOpt("bind").create("b"); + private static final Option OPTION_CONFIGURATION_STORE_PATH = OptionBuilder.withArgName("path").hasArg() + .withDescription("use given configuration store location").withLongOpt("store-path").create("sp"); + + private static final Option OPTION_CONFIGURATION_STORE_TYPE = OptionBuilder.withArgName("type").hasArg() + .withDescription("use given store type").withLongOpt("store-type").create("st"); + + private static final Option OPTION_INITIAL_CONFIGURATION_STORE_PATH = OptionBuilder.withArgName("path").hasArg() + .withDescription("pass the location of initial store to use to create a user store").withLongOpt("initial-store-path").create("isp"); + + private static final Option OPTION_INITIAL_CONFIGURATION_STORE_TYPE = OptionBuilder.withArgName("type").hasArg() + .withDescription("the type of initial store").withLongOpt("initial-store-type").create("ist"); private static final Option OPTION_LOG_CONFIG_FILE = OptionBuilder.withArgName("file").hasArg() @@ -137,31 +65,31 @@ private static final Option OPTION_INCLUDE_0_8 = .withDescription("monitor the log file configuration file for changes. Units are seconds. " + "Zero means do not check for changes.").withLongOpt("logwatch").create("w"); + private static final Option OPTION_MANAGEMENT_MODE = OptionBuilder.withDescription("start broker in a management mode") + .withLongOpt("management-mode").create("mm"); + private static final Option OPTION_RMI_PORT = OptionBuilder.withArgName("port").hasArg() + .withDescription("override jmx rmi port in management mode").withLongOpt("jmxregistryport").create("rmi"); + private static final Option OPTION_CONNECTOR_PORT = OptionBuilder.withArgName("port").hasArg() + .withDescription("override jmx connector port in management mode").withLongOpt("jmxconnectorport").create("jmxrmi"); + private static final Option OPTION_HTTP_PORT = OptionBuilder.withArgName("port").hasArg() + .withDescription("override web management port in management mode").withLongOpt("httpport").create("http"); + private static final Options OPTIONS = new Options(); static { OPTIONS.addOption(OPTION_HELP); OPTIONS.addOption(OPTION_VERSION); - OPTIONS.addOption(OPTION_CONFIG_FILE); + OPTIONS.addOption(OPTION_CONFIGURATION_STORE_PATH); + OPTIONS.addOption(OPTION_CONFIGURATION_STORE_TYPE); OPTIONS.addOption(OPTION_LOG_CONFIG_FILE); OPTIONS.addOption(OPTION_LOG_WATCH); - OPTIONS.addOption(OPTION_PORT); - OPTIONS.addOption(OPTION_SSLPORT); - OPTIONS.addOption(OPTION_EXCLUDE_1_0); - OPTIONS.addOption(OPTION_EXCLUDE_0_10); - OPTIONS.addOption(OPTION_EXCLUDE_0_9_1); - OPTIONS.addOption(OPTION_EXCLUDE_0_9); - OPTIONS.addOption(OPTION_EXCLUDE_0_8); - OPTIONS.addOption(OPTION_INCLUDE_1_0); - OPTIONS.addOption(OPTION_INCLUDE_0_10); - OPTIONS.addOption(OPTION_INCLUDE_0_9_1); - OPTIONS.addOption(OPTION_INCLUDE_0_9); - OPTIONS.addOption(OPTION_INCLUDE_0_8); - OPTIONS.addOption(OPTION_BIND); - - OPTIONS.addOption(OPTION_JMX_PORT_REGISTRY_SERVER); - OPTIONS.addOption(OPTION_JMX_PORT_CONNECTOR_SERVER); + OPTIONS.addOption(OPTION_INITIAL_CONFIGURATION_STORE_PATH); + OPTIONS.addOption(OPTION_INITIAL_CONFIGURATION_STORE_TYPE); + OPTIONS.addOption(OPTION_MANAGEMENT_MODE); + OPTIONS.addOption(OPTION_RMI_PORT); + OPTIONS.addOption(OPTION_CONNECTOR_PORT); + OPTIONS.addOption(OPTION_HTTP_PORT); } protected CommandLine _commandLine; @@ -243,10 +171,15 @@ private static final Option OPTION_INCLUDE_0_8 = else { BrokerOptions options = new BrokerOptions(); - String configFile = _commandLine.getOptionValue(OPTION_CONFIG_FILE.getOpt()); - if(configFile != null) + String configurationStore = _commandLine.getOptionValue(OPTION_CONFIGURATION_STORE_PATH.getOpt()); + if (configurationStore != null) + { + options.setConfigurationStoreLocation(configurationStore); + } + String configurationStoreType = _commandLine.getOptionValue(OPTION_CONFIGURATION_STORE_TYPE.getOpt()); + if (configurationStoreType != null) { - options.setConfigFile(configFile); + options.setConfigurationStoreType(configurationStoreType); } String logWatchConfig = _commandLine.getOptionValue(OPTION_LOG_WATCH.getOpt()); @@ -261,52 +194,37 @@ private static final Option OPTION_INCLUDE_0_8 = options.setLogConfigFile(logConfig); } - String jmxPortRegistryServer = _commandLine.getOptionValue(OPTION_JMX_PORT_REGISTRY_SERVER.getOpt()); - if(jmxPortRegistryServer != null) + String initialConfigurationStore = _commandLine.getOptionValue(OPTION_INITIAL_CONFIGURATION_STORE_PATH.getOpt()); + if (initialConfigurationStore != null) { - options.setJmxPortRegistryServer(Integer.parseInt(jmxPortRegistryServer)); + options.setInitialConfigurationStoreLocation(initialConfigurationStore); } - - String jmxPortConnectorServer = _commandLine.getOptionValue(OPTION_JMX_PORT_CONNECTOR_SERVER.getLongOpt()); - if(jmxPortConnectorServer != null) - { - options.setJmxPortConnectorServer(Integer.parseInt(jmxPortConnectorServer)); - } - - String bindAddr = _commandLine.getOptionValue(OPTION_BIND.getOpt()); - if (bindAddr != null) + String initailConfigurationStoreType = _commandLine.getOptionValue(OPTION_INITIAL_CONFIGURATION_STORE_TYPE.getOpt()); + if (initailConfigurationStoreType != null) { - options.setBind(bindAddr); + options.setInitialConfigurationStoreType(initailConfigurationStoreType); } - String[] portStr = _commandLine.getOptionValues(OPTION_PORT.getOpt()); - if(portStr != null) + boolean managmentMode = _commandLine.hasOption(OPTION_MANAGEMENT_MODE.getOpt()); + if (managmentMode) { - parsePortArray(options, portStr, false); - for(ProtocolExclusion pe : ProtocolExclusion.values()) + options.setManagementMode(true); + String rmiPort = _commandLine.getOptionValue(OPTION_RMI_PORT.getOpt()); + if (rmiPort != null) { - parsePortArray(options, _commandLine.getOptionValues(pe.getExcludeName()), pe); + options.setManagementModeRmiPort(Integer.parseInt(rmiPort)); } - for(ProtocolInclusion pe : ProtocolInclusion.values()) + String connectorPort = _commandLine.getOptionValue(OPTION_CONNECTOR_PORT.getOpt()); + if (connectorPort != null) { - parseProtocolInclusions(options, _commandLine.getOptionValues(pe.getIncludeName()), pe); + options.setManagementModeConnectorPort(Integer.parseInt(connectorPort)); } - } - - String[] sslPortStr = _commandLine.getOptionValues(OPTION_SSLPORT.getOpt()); - if(sslPortStr != null) - { - parsePortArray(options, sslPortStr, true); - for(ProtocolExclusion pe : ProtocolExclusion.values()) + String httpPort = _commandLine.getOptionValue(OPTION_HTTP_PORT.getOpt()); + if (httpPort != null) { - parsePortArray(options, _commandLine.getOptionValues(pe.getExcludeName()), pe); - } - for(ProtocolInclusion pe : ProtocolInclusion.values()) - { - parseProtocolInclusions(options, _commandLine.getOptionValues(pe.getIncludeName()), pe); + options.setManagementModeHttpPort(Integer.parseInt(httpPort)); } } - setExceptionHandler(); startBroker(options); @@ -389,72 +307,7 @@ private static final Option OPTION_INCLUDE_0_8 = protected void shutdown(final int status) { - ApplicationRegistry.remove(); System.exit(status); } - private static void parsePortArray(final BrokerOptions options,final Object[] ports, - final boolean ssl) throws InitException - { - if(ports != null) - { - for(int i = 0; i < ports.length; i++) - { - try - { - if(ssl) - { - options.addSSLPort(Integer.parseInt(String.valueOf(ports[i]))); - } - else - { - options.addPort(Integer.parseInt(String.valueOf(ports[i]))); - } - } - catch (NumberFormatException e) - { - throw new InitException("Invalid port: " + ports[i], e); - } - } - } - } - - private static void parsePortArray(final BrokerOptions options, final Object[] ports, - final ProtocolExclusion excludedProtocol) throws InitException - { - if(ports != null) - { - for(int i = 0; i < ports.length; i++) - { - try - { - options.addExcludedPort(excludedProtocol, - Integer.parseInt(String.valueOf(ports[i]))); - } - catch (NumberFormatException e) - { - throw new InitException("Invalid port for exclusion: " + ports[i], e); - } - } - } - } - - private static void parseProtocolInclusions(final BrokerOptions options, final Object[] ports, - final ProtocolInclusion includedProtocol) throws InitException - { - if(ports != null) - { - for(int i = 0; i < ports.length; i++) - { - try - { - options.addIncludedPort(includedProtocol, Integer.parseInt(String.valueOf(ports[i]))); - } - catch (NumberFormatException e) - { - throw new InitException("Invalid port for inclusion: " + ports[i], e); - } - } - } - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java b/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java deleted file mode 100644 index fe6e32173f..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server; - -import java.util.HashMap; -import java.util.Map; - -public enum ProtocolExclusion -{ - v0_8("exclude-0-8","--exclude-0-8"), - v0_9("exclude-0-9", "--exclude-0-9"), - v0_9_1("exclude-0-9-1", "--exclude-0-9-1"), - v0_10("exclude-0-10", "--exclude-0-10"), - v1_0("exclude-1-0", "--exclude-1-0"); - - private static final Map MAP = new HashMap(); - - static - { - for(ProtocolExclusion pe : ProtocolExclusion.values()) - { - MAP.put(pe.getArg(), pe); - } - } - - private String _arg; - private String _excludeName; - - private ProtocolExclusion(final String excludeName, final String arg) - { - _excludeName = excludeName; - _arg = arg; - } - - public String getArg() - { - return _arg; - } - - public String getExcludeName() - { - return _excludeName; - } - - public static ProtocolExclusion lookup(final String arg) - { - ProtocolExclusion ex = MAP.get(arg); - - if(ex == null) - { - throw new IllegalArgumentException(arg + " is not a valid protocol exclusion"); - } - - return ex; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java b/java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java deleted file mode 100644 index 85fbe2e02e..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server; - -import java.util.HashMap; -import java.util.Map; - -public enum ProtocolInclusion -{ - v0_8("include-0-8","--include-0-8"), - v0_9("include-0-9", "--include-0-9"), - v0_9_1("include-0-9-1", "--include-0-9-1"), - v0_10("include-0-10", "--include-0-10"), - v1_0("include-1-0", "--include-1-0"); - - private static final Map MAP = new HashMap(); - - static - { - for(ProtocolInclusion pe : ProtocolInclusion.values()) - { - MAP.put(pe.getArg(), pe); - } - } - - private String _arg; - private String _includeName; - - private ProtocolInclusion(final String includeName, final String arg) - { - _includeName = includeName; - _arg = arg; - } - - public String getArg() - { - return _arg; - } - - public String getIncludeName() - { - return _includeName; - } - - public static ProtocolInclusion lookup(final String arg) - { - ProtocolInclusion ex = MAP.get(arg); - - if(ex == null) - { - throw new IllegalArgumentException(arg + " is not a valid protocol inclusion"); - } - - return ex; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java b/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java index 0c474cca13..b7007bf768 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java +++ b/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java @@ -18,46 +18,85 @@ */ package org.apache.qpid.server; -import org.apache.log4j.Logger; +import org.apache.qpid.AMQException; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogMessage; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ChannelMessages; +import org.apache.qpid.server.txn.ServerTransaction; public class TransactionTimeoutHelper { - private static final Logger LOGGER = Logger.getLogger(TransactionTimeoutHelper.class); - - public static final String IDLE_TRANSACTION_ALERT = "IDLE TRANSACTION ALERT"; - public static final String OPEN_TRANSACTION_ALERT = "OPEN TRANSACTION ALERT"; + private static final String OPEN_TRANSACTION_TIMEOUT_ERROR = "Open transaction timed out"; + private static final String IDLE_TRANSACTION_TIMEOUT_ERROR = "Idle transaction timed out"; private final LogSubject _logSubject; - public TransactionTimeoutHelper(final LogSubject logSubject) + private final CloseAction _closeAction; + + public TransactionTimeoutHelper(final LogSubject logSubject, final CloseAction closeAction) { _logSubject = logSubject; + _closeAction = closeAction; } - public void logIfNecessary(final long timeSoFar, final long warnTimeout, - final LogMessage message, final String alternateLogPrefix) + public void checkIdleOrOpenTimes(ServerTransaction transaction, long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException { - if (isTimedOut(timeSoFar, warnTimeout)) + if (transaction.isTransactional()) { - LogActor logActor = CurrentActor.get(); - if(logActor.getRootMessageLogger().isMessageEnabled(logActor, _logSubject, message.getLogHierarchy())) + final long transactionUpdateTime = transaction.getTransactionUpdateTime(); + if(transactionUpdateTime > 0) { - logActor.message(_logSubject, message); + long idleTime = System.currentTimeMillis() - transactionUpdateTime; + boolean closed = logAndCloseIfNecessary(idleTime, idleWarn, idleClose, ChannelMessages.IDLE_TXN(idleTime), IDLE_TRANSACTION_TIMEOUT_ERROR); + if (closed) + { + return; // no point proceeding to check the open time + } } - else + + final long transactionStartTime = transaction.getTransactionStartTime(); + if(transactionStartTime > 0) { - LOGGER.warn(alternateLogPrefix + " " + _logSubject.toLogString() + " " + timeSoFar + " ms"); + long openTime = System.currentTimeMillis() - transactionStartTime; + logAndCloseIfNecessary(openTime, openWarn, openClose, ChannelMessages.OPEN_TXN(openTime), OPEN_TRANSACTION_TIMEOUT_ERROR); } } } - public boolean isTimedOut(long timeSoFar, long timeout) + /** + * @return true iff closeTimeout was exceeded + */ + private boolean logAndCloseIfNecessary(final long timeSoFar, + final long warnTimeout, final long closeTimeout, + final LogMessage warnMessage, final String closeMessage) throws AMQException + { + if (isTimedOut(timeSoFar, warnTimeout)) + { + LogActor logActor = CurrentActor.get(); + logActor.message(_logSubject, warnMessage); + } + + if(isTimedOut(timeSoFar, closeTimeout)) + { + _closeAction.doTimeoutAction(closeMessage); + return true; + } + else + { + return false; + } + } + + private boolean isTimedOut(long timeSoFar, long timeout) { return timeout > 0L && timeSoFar > timeout; } + + public interface CloseAction + { + void doTimeoutAction(String reason) throws AMQException; + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java index 9b3be624e0..469a4bb9d0 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java +++ b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java @@ -35,13 +35,15 @@ public class Binding private final Exchange _exchange; private final Map _arguments; private final UUID _id; - private final UUID _qmfId; private final AtomicLong _matches = new AtomicLong(); - public Binding(UUID id, UUID qmfId, final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map arguments) + public Binding(UUID id, + final String bindingKey, + final AMQQueue queue, + final Exchange exchange, + final Map arguments) { _id = id; - _qmfId = qmfId; _bindingKey = bindingKey; _queue = queue; _exchange = exchange; @@ -53,11 +55,6 @@ public class Binding return _id; } - public UUID getQMFId() - { - return _qmfId; - } - public String getBindingKey() { return _bindingKey; diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java index b805056311..69ff081528 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java @@ -24,10 +24,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.BindingConfig; -import org.apache.qpid.server.configuration.BindingConfigType; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.BindingMessages; @@ -52,7 +48,7 @@ public class BindingFactory _virtualHost = vhost; } - private final class BindingImpl extends Binding implements AMQQueue.Task, Exchange.Task, BindingConfig + private final class BindingImpl extends Binding implements AMQQueue.Task, Exchange.Task { private final BindingLogSubject _logSubject; //TODO : persist creation time @@ -60,7 +56,7 @@ public class BindingFactory private BindingImpl(UUID id, String bindingKey, final AMQQueue queue, final Exchange exchange, final Map arguments) { - super(id, queue.getVirtualHost().getConfigStore().createId(), bindingKey, queue, exchange, arguments); + super(id, bindingKey, queue, exchange, arguments); _logSubject = new BindingLogSubject(bindingKey,exchange,queue); } @@ -96,16 +92,6 @@ public class BindingFactory return _createTime; } - public BindingConfigType getConfigType() - { - return BindingConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return _virtualHost; - } - public boolean isDurable() { return getQueue().isDurable() && getExchange().isDurable(); @@ -186,7 +172,6 @@ public class BindingFactory exchange.addCloseTask(b); queue.addBinding(b); exchange.addBinding(b); - getConfigStore().addConfiguredObject(b); b.logCreation(); return true; @@ -197,11 +182,6 @@ public class BindingFactory } } - private ConfigStore getConfigStore() - { - return _virtualHost.getConfigStore(); - } - public void restoreBinding(final UUID id, final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map argumentMap) throws AMQSecurityException, AMQInternalException { makeBinding(id, bindingKey,queue,exchange,argumentMap,true, false); @@ -257,7 +237,6 @@ public class BindingFactory _virtualHost.getMessageStore().unbindQueue(b); } b.logDestruction(); - getConfigStore().removeConfiguredObject(b); } return b; diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfig.java deleted file mode 100644 index 233134abc5..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.server.configuration; - -import java.util.Map; - - -public interface BindingConfig extends ConfiguredObject -{ - - ExchangeConfig getExchange(); - - QueueConfig getQueue(); - - String getBindingKey(); - - Map getArguments(); - - String getOrigin(); - - long getMatches(); -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfigType.java deleted file mode 100644 index 1ed6b38758..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfigType.java +++ /dev/null @@ -1,114 +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.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public final class BindingConfigType extends ConfigObjectType -{ - private static final List> BINDING_PROPERTIES = new ArrayList>(); - - public static interface BindingProperty extends ConfigProperty - { - } - - private abstract static class BindingReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements BindingProperty - { - public BindingReadWriteProperty(String name) - { - super(name); - BINDING_PROPERTIES.add(this); - } - } - - private abstract static class BindingReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements BindingProperty - { - public BindingReadOnlyProperty(String name) - { - super(name); - BINDING_PROPERTIES.add(this); - } - } - - public static final BindingReadOnlyProperty EXCHANGE_PROPERTY = new BindingReadOnlyProperty("exchange") - { - public ExchangeConfig getValue(BindingConfig object) - { - return object.getExchange(); - } - }; - - public static final BindingReadOnlyProperty QUEUE_PROPERTY = new BindingReadOnlyProperty("queue") - { - public QueueConfig getValue(BindingConfig object) - { - return object.getQueue(); - } - }; - - public static final BindingReadOnlyProperty BINDING_KEY_PROPERTY = new BindingReadOnlyProperty("bindingKey") - { - public String getValue(BindingConfig object) - { - return object.getBindingKey(); - } - }; - - public static final BindingReadOnlyProperty> ARGUMENTS = new BindingReadOnlyProperty>("arguments") - { - public Map getValue(BindingConfig object) - { - return object.getArguments(); - } - }; - - public static final BindingReadOnlyProperty ORIGIN_PROPERTY = new BindingReadOnlyProperty("origin") - { - public String getValue(BindingConfig object) - { - return object.getOrigin(); - } - }; - - private static final BindingConfigType INSTANCE = new BindingConfigType(); - - private BindingConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(BINDING_PROPERTIES); - } - - public static BindingConfigType getInstance() - { - return INSTANCE; - } - - - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfig.java deleted file mode 100644 index 00ed5fd0dd..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfig.java +++ /dev/null @@ -1,48 +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.configuration; - -public interface BridgeConfig extends ConfiguredObject -{ - - boolean isDynamic(); - - boolean isQueueBridge(); - - boolean isLocalSource(); - - String getSource(); - - String getDestination(); - - String getKey(); - - String getTag(); - - String getExcludes(); - - LinkConfig getLink(); - - Integer getChannelId(); - - int getAckBatching(); -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfigType.java deleted file mode 100644 index 888feeff0c..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfigType.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.server.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -public final class BridgeConfigType extends ConfigObjectType -{ - private static final List> BRIDGE_PROPERTIES = new ArrayList>(); - - public static interface BridgeProperty extends ConfigProperty - { - } - - private abstract static class BridgeReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements BridgeProperty - { - public BridgeReadWriteProperty(String name) - { - super(name); - BRIDGE_PROPERTIES.add(this); - } - } - - private abstract static class BridgeReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements BridgeProperty - { - public BridgeReadOnlyProperty(String name) - { - super(name); - BRIDGE_PROPERTIES.add(this); - } - } - - public static final BridgeReadOnlyProperty LINK_PROPERTY = new BridgeReadOnlyProperty("link") - { - public LinkConfig getValue(BridgeConfig object) - { - return object.getLink(); - } - }; - - public static final BridgeReadOnlyProperty CHANNEL_ID_PROPERTY = new BridgeReadOnlyProperty("channelId") - { - public Integer getValue(BridgeConfig object) - { - return object.getChannelId(); - } - }; - - public static final BridgeReadOnlyProperty DURABLE_PROPERTY = new BridgeReadOnlyProperty("durable") - { - public Boolean getValue(BridgeConfig object) - { - return object.isDurable(); - } - }; - - public static final BridgeReadOnlyProperty SOURCE_PROPERTY = new BridgeReadOnlyProperty("source") - { - public String getValue(BridgeConfig object) - { - return object.getSource(); - } - }; - - public static final BridgeReadOnlyProperty DESTINATION_PROPERTY = new BridgeReadOnlyProperty("destination") - { - public String getValue(BridgeConfig object) - { - return object.getDestination(); - } - }; - - public static final BridgeReadOnlyProperty KEY_PROPERTY = new BridgeReadOnlyProperty("key") - { - public String getValue(BridgeConfig object) - { - return object.getKey(); - } - }; - - public static final BridgeReadOnlyProperty QUEUE_BRIDGE_PROPERTY = new BridgeReadOnlyProperty("queueBridge") - { - public Boolean getValue(BridgeConfig object) - { - return object.isQueueBridge(); - } - }; - - public static final BridgeReadOnlyProperty LOCAL_SOURCE_PROPERTY = new BridgeReadOnlyProperty("localSource") - { - public Boolean getValue(BridgeConfig object) - { - return object.isLocalSource(); - } - }; - - public static final BridgeReadOnlyProperty TAG_PROPERTY = new BridgeReadOnlyProperty("tag") - { - public String getValue(BridgeConfig object) - { - return object.getTag(); - } - }; - - public static final BridgeReadOnlyProperty EXCLUDES_PROPERTY = new BridgeReadOnlyProperty("excludes") - { - public String getValue(BridgeConfig object) - { - return object.getExcludes(); - } - }; - - public static final BridgeReadOnlyProperty DYNAMIC_PROPERTY = new BridgeReadOnlyProperty("dynamic") - { - public Boolean getValue(BridgeConfig object) - { - return object.isDynamic(); - } - }; - - public static final BridgeReadOnlyProperty ACK_BATCHING_PROPERTY = new BridgeReadOnlyProperty("ackBatching") - { - public Integer getValue(BridgeConfig object) - { - return object.getAckBatching(); - } - }; - - - private static final BridgeConfigType INSTANCE = new BridgeConfigType(); - - private BridgeConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(BRIDGE_PROPERTIES); - } - - public static BridgeConfigType getInstance() - { - return INSTANCE; - } - - - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfig.java deleted file mode 100644 index 7dffc2d3c0..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfig.java +++ /dev/null @@ -1,71 +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.configuration; - -import java.util.List; - - -public interface BrokerConfig extends ConfiguredObject -{ - void setSystem(SystemConfig system); - - SystemConfig getSystem(); - - Integer getPort(); - - Integer getWorkerThreads(); - - Integer getMaxConnections(); - - Integer getConnectionBacklogLimit(); - - Long getStagingThreshold(); - - Integer getManagementPublishInterval(); - - String getVersion(); - - String getDataDirectory(); - - String getFederationTag(); - - /** - * List of feature(s) to be advertised to clients on connection. - * Feature names are strings, beginning with qpid. followed by more or more - * words separated by minus signs e.g. qpid.jms-selector. - * - * If there are no features, this method must return an empty array. - * - * @return list of feature names - */ - List getFeatures(); - - void addVirtualHost(VirtualHostConfig virtualHost); - - void createBrokerConnection(String transport, - String host, - int port, - boolean durable, - String authMechanism, - String username, String password); - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigType.java deleted file mode 100644 index 64a59c3f61..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigType.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.server.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -public final class BrokerConfigType extends ConfigObjectType -{ - private static final List> BROKER_PROPERTIES = new ArrayList>(); - - public static interface BrokerProperty extends ConfigProperty - { - } - - private abstract static class BrokerReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements BrokerProperty - { - public BrokerReadWriteProperty(String name) - { - super(name); - BROKER_PROPERTIES.add(this); - } - } - - private abstract static class BrokerReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements BrokerProperty - { - public BrokerReadOnlyProperty(String name) - { - super(name); - BROKER_PROPERTIES.add(this); - } - } - - public static final BrokerReadOnlyProperty SYSTEM_PROPERTY = new BrokerReadOnlyProperty("system") - { - public SystemConfig getValue(BrokerConfig object) - { - return object.getSystem(); - } - }; - - public static final BrokerReadOnlyProperty PORT_PROPERTY = new BrokerReadOnlyProperty("port") - { - public Integer getValue(BrokerConfig object) - { - return object.getPort(); - } - }; - - public static final BrokerReadOnlyProperty WORKER_THREADS_PROPERTY = new BrokerReadOnlyProperty("workerThreads") - { - public Integer getValue(BrokerConfig object) - { - return object.getWorkerThreads(); - } - }; - - public static final BrokerReadOnlyProperty MAX_CONNECTIONS_PROPERTY = new BrokerReadOnlyProperty("maxConnections") - { - public Integer getValue(BrokerConfig object) - { - return object.getMaxConnections(); - } - }; - - public static final BrokerReadOnlyProperty CONNECTION_BACKLOG_LIMIT_PROPERTY = new BrokerReadOnlyProperty("connectionBacklog") - { - public Integer getValue(BrokerConfig object) - { - return object.getConnectionBacklogLimit(); - } - }; - - public static final BrokerReadOnlyProperty STAGING_THRESHOLD_PROPERTY = new BrokerReadOnlyProperty("stagingThreshold") - { - public Long getValue(BrokerConfig object) - { - return object.getStagingThreshold(); - } - }; - - public static final BrokerReadOnlyProperty MANAGEMENT_PUBLISH_INTERVAL_PROPERTY = new BrokerReadOnlyProperty("mgmtPublishInterval") - { - public Integer getValue(BrokerConfig object) - { - return object.getManagementPublishInterval(); - } - }; - - public static final BrokerReadOnlyProperty VERSION_PROPERTY = new BrokerReadOnlyProperty("version") - { - public String getValue(BrokerConfig object) - { - return object.getVersion(); - } - }; - - public static final BrokerReadOnlyProperty DATA_DIR_PROPERTY = new BrokerReadOnlyProperty("dataDirectory") - { - public String getValue(BrokerConfig object) - { - return object.getDataDirectory(); - } - }; - - private static final BrokerConfigType INSTANCE = new BrokerConfigType(); - - private BrokerConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(BROKER_PROPERTIES); - } - - public static BrokerConfigType getInstance() - { - return INSTANCE; - } - - - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreator.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreator.java new file mode 100644 index 0000000000..31e08ab88a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreator.java @@ -0,0 +1,102 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +/** + * A helper class responsible for creation and opening of broker store. + */ +public class BrokerConfigurationStoreCreator +{ + /** + * URL to resource containing broker default configuration + */ + public static final String DEFAULT_INITIAL_STORE_LOCATION = BrokerConfigurationStoreCreator.class.getClassLoader() + .getResource("initial-store.json").toExternalForm(); + + private Map _factories = new HashMap(); + + public BrokerConfigurationStoreCreator() + { + QpidServiceLoader serviceLoader = new QpidServiceLoader(); + Iterable configurationStoreFactories = serviceLoader + .instancesOf(ConfigurationStoreFactory.class); + for (ConfigurationStoreFactory storeFactory : configurationStoreFactories) + { + String type = storeFactory.getStoreType(); + ConfigurationStoreFactory factory = _factories.put(type.toLowerCase(), storeFactory); + if (factory != null) + { + throw new IllegalStateException("ConfigurationStoreFactory with type name '" + type + + "' is already registered using class '" + factory.getClass().getName() + "', can not register class '" + + storeFactory.getClass().getName() + "'"); + } + } + } + + /** + * Create broker configuration store for a given store location, store type, initial store location and initial store type + * + * @param storeLocation store location + * @param storeType store type + * @param initialStoreLocation initial store location + * @param initialStoreType initial store type + * @return store instance opened at given store location + * @throws IllegalConfigurationException if store type is unknown + */ + public ConfigurationEntryStore createStore(String storeLocation, String storeType, String initialStoreLocation, + String initialStoreType) + { + ConfigurationEntryStore store = createStore(storeType); + if (initialStoreLocation == null) + { + initialStoreLocation = DEFAULT_INITIAL_STORE_LOCATION; + initialStoreType = JsonConfigurationEntryStore.STORE_TYPE; + } + if (storeType.equals(initialStoreType)) + { + store.open(storeLocation, initialStoreLocation); + } + else + { + ConfigurationEntryStore initialStore = createStore(initialStoreType); + initialStore.open(initialStoreLocation); + store.open(storeLocation, initialStore); + } + return store; + } + + private ConfigurationEntryStore createStore(String storeType) + { + ConfigurationStoreFactory factory = _factories.get(storeType.toLowerCase()); + if (factory == null) + { + throw new IllegalConfigurationException("Unknown store type: " + storeType); + } + return factory.createStore(); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerProperties.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerProperties.java new file mode 100644 index 0000000000..179d4a5640 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerProperties.java @@ -0,0 +1,54 @@ +package org.apache.qpid.server.configuration; + +import java.util.Locale; + +/** + * Declares broker system property names + */ +public class BrokerProperties +{ + public static final int DEFAULT_HEART_BEAT_TIMEOUT_FACTOR = 2; + + public static final String PROPERTY_DEAD_LETTER_EXCHANGE_SUFFIX = "qpid.dead_letter_exchange_suffix"; + public static final String PROPERTY_DEAD_LETTER_QUEUE_SUFFIX = "qpid.dead_letter_queue_suffix"; + + public static final String PROPERTY_FRAME_SIZE = "qpid.frame_size"; + public static final String PROPERTY_MSG_AUTH = "qpid.msg_auth"; + public static final String PROPERTY_STATUS_UPDATES = "qpid.status_updates"; + public static final String PROPERTY_LOCALE = "qpid.locale"; + public static final String PROPERTY_DEFAULT_SUPPORTED_PROTOCOL_REPLY = "qpid.default_supported_protocol_version_reply"; + public static final String PROPERTY_DISABLED_FEATURES = "qpid.broker_disabled_features"; + + public static final int DEFAULT_FRAME_SIZE = Integer.getInteger(PROPERTY_FRAME_SIZE, 65535); + public static final String PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES = "qpid.broker_default_amqp_protocol_excludes"; + public static final String PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES = "qpid.broker_default_amqp_protocol_includes"; + + public static final String PROPERTY_MANAGEMENT_RIGHTS_INFER_ALL_ACCESS = "qpid.broker_jmx_method_rights_infer_all_access"; + public static final String PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY = "qpid.broker_jmx_use_custom_rmi_socket_factory"; + + public static final String PROPERTY_QPID_HOME = "QPID_HOME"; + public static final String PROPERTY_QPID_WORK = "QPID_WORK"; + + private BrokerProperties() + { + } + + public static Locale getLocale() + { + Locale locale = Locale.US; + String localeSetting = System.getProperty(BrokerProperties.PROPERTY_LOCALE); + if (localeSetting != null) + { + String[] localeParts = localeSetting.split("_"); + String language = (localeParts.length > 0 ? localeParts[0] : ""); + String country = (localeParts.length > 1 ? localeParts[1] : ""); + String variant = ""; + if (localeParts.length > 2) + { + variant = localeSetting.substring(language.length() + 1 + country.length() + 1); + } + locale = new Locale(language, country, variant); + } + return locale; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigObjectType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigObjectType.java deleted file mode 100644 index c45aaaf1ee..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigObjectType.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.server.configuration; - -import java.util.Collection; - -public abstract class ConfigObjectType, C extends ConfiguredObject> -{ - public abstract Collection> getProperties(); - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigProperty.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigProperty.java deleted file mode 100644 index 2d88ba00a0..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigProperty.java +++ /dev/null @@ -1,66 +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.configuration; - -public interface ConfigProperty, C extends ConfiguredObject, S> -{ - public String getName(); - - public S getValue(C object); - - public void setValue(C object, S value); - - public void clearValue(C object); - - public abstract static class ReadWriteConfigProperty, C extends ConfiguredObject,S> implements ConfigProperty - { - private final String _name; - - protected ReadWriteConfigProperty(String name) - { - _name = name; - } - - public final String getName() - { - return _name; - } - } - - public abstract static class ReadOnlyConfigProperty, C extends ConfiguredObject, S> extends ReadWriteConfigProperty - { - protected ReadOnlyConfigProperty(String name) - { - super(name); - } - - public final void setValue(C object, S value) - { - throw new UnsupportedOperationException("Cannot set value '"+getName()+"' as this property is read-only"); - } - - public final void clearValue(C object) - { - throw new UnsupportedOperationException("Cannot set value '"+getName()+"' as this property is read-only"); - } - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java deleted file mode 100644 index c519a0c0fa..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java +++ /dev/null @@ -1,201 +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.configuration; - -import java.util.Collection; -import java.util.Collections; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; - -public class ConfigStore -{ - private ConcurrentHashMap> _typeMap = - new ConcurrentHashMap>(); - - private ConcurrentHashMap> _listenerMap = - new ConcurrentHashMap>(); - - private AtomicReference _root = new AtomicReference(null); - - private final AtomicLong _objectIdSource = new AtomicLong(0l); - private final AtomicLong _persistentObjectIdSource = new AtomicLong(0l); - - // TODO - should load/increment this on broker startup - private long _sequenceNumber = 1L; - - public enum Event - { - CREATED, DELETED - } - - public interface ConfigEventListener, C extends ConfiguredObject> - { - void onEvent(C object, Event evt); - } - - private ConfigStore() - { - } - - public , C extends ConfiguredObject> ConfiguredObject getConfiguredObject(ConfigObjectType type, UUID id) - { - ConcurrentHashMap typeMap = _typeMap.get(type); - if(typeMap != null) - { - return typeMap.get(id); - } - else - { - return null; - } - - } - - public , C extends ConfiguredObject> Collection getConfiguredObjects(ConfigObjectType type) - { - ConcurrentHashMap typeMap = _typeMap.get(type); - if(typeMap != null) - { - return typeMap.values(); - } - else - { - return Collections.EMPTY_LIST; - } - - } - - public , C extends ConfiguredObject> void addConfiguredObject(ConfiguredObject object) - { - ConcurrentHashMap typeMap = _typeMap.get(object.getConfigType()); - if(typeMap == null) - { - typeMap = new ConcurrentHashMap(); - ConcurrentHashMap oldMap = _typeMap.putIfAbsent(object.getConfigType(), typeMap); - if(oldMap != null) - { - typeMap = oldMap; - } - - } - - typeMap.put(object.getQMFId(), object); - sendEvent(Event.CREATED, object); - } - - - public , C extends ConfiguredObject> void removeConfiguredObject(ConfiguredObject object) - { - ConcurrentHashMap typeMap = _typeMap.get(object.getConfigType()); - if(typeMap != null) - { - typeMap.remove(object.getQMFId()); - sendEvent(Event.DELETED, object); - } - } - - public , C extends ConfiguredObject> void addConfigEventListener(T type, ConfigEventListener listener) - { - CopyOnWriteArrayList listeners = _listenerMap.get(type); - if(listeners == null) - { - listeners = new CopyOnWriteArrayList(); - CopyOnWriteArrayList oldListeners = _listenerMap.putIfAbsent(type, listeners); - if(oldListeners != null) - { - listeners = oldListeners; - } - - } - - listeners.add(listener); - - } - - public , C extends ConfiguredObject> void removeConfigEventListener(T type, ConfigEventListener listener) - { - CopyOnWriteArrayList listeners = _listenerMap.get(type); - if(listeners != null) - { - listeners.remove(listener); - } - } - - private void sendEvent(Event e, ConfiguredObject o) - { - CopyOnWriteArrayList listeners = _listenerMap.get(o.getConfigType()); - if(listeners != null) - { - for(ConfigEventListener listener : listeners) - { - listener.onEvent(o, e); - } - } - } - - public boolean setRoot(SystemConfig object) - { - if(_root.compareAndSet(null,object)) - { - addConfiguredObject(object); - return true; - } - else - { - return false; - } - } - - public UUID createId() - { - return new UUID(((_sequenceNumber & 0xFFFl)<<48), _objectIdSource.incrementAndGet()); - } - - public UUID createPersistentId() - { - return new UUID(0L, _persistentObjectIdSource.incrementAndGet()); - } - - public void persistentIdInUse(UUID id) - { - long lsb = id.getLeastSignificantBits(); - long currentId; - while((currentId = _persistentObjectIdSource.get()) < lsb) - { - _persistentObjectIdSource.compareAndSet(currentId, lsb); - } - } - - public SystemConfig getRoot() - { - return _root.get(); - } - - public static ConfigStore newInstance() - { - return new ConfigStore(); - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntry.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntry.java new file mode 100644 index 0000000000..8afb1af24d --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntry.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.server.configuration; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +public class ConfigurationEntry +{ + public static final String ATTRIBUTE_NAME = "name"; + + private final UUID _id; + private final String _type; + private final Map _attributes; + private final Set _childrenIds; + private final ConfigurationEntryStore _store; + + public ConfigurationEntry(UUID id, String type, Map attributes, Set childrenIds, + ConfigurationEntryStore store) + { + super(); + _id = id; + _type = type; + _attributes = attributes; + _childrenIds = childrenIds; + _store = store; + } + + public UUID getId() + { + return _id; + } + + public String getType() + { + return _type; + } + + public Map getAttributes() + { + return _attributes; + } + + public Set getChildrenIds() + { + return _childrenIds; + } + + public ConfigurationEntryStore getStore() + { + return _store; + } + + /** + * Returns this entry's children. The collection should not be modified. + */ + public Map> getChildren() + { + Map> children = null; + if (_childrenIds == null) + { + children = Collections.emptyMap(); + } + else + { + children = new HashMap>(); + for (UUID childId : _childrenIds) + { + ConfigurationEntry entry = _store.getEntry(childId); + String type = entry.getType(); + Collection childrenOfType = children.get(type); + if (childrenOfType == null) + { + childrenOfType = new ArrayList(); + children.put(type, childrenOfType); + } + childrenOfType.add(entry); + } + } + return Collections.unmodifiableMap(children); + } + + public boolean hasChild(UUID id) + { + return _childrenIds.contains(id); + } + + @Override + public int hashCode() + { + return _id.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + + ConfigurationEntry other = (ConfigurationEntry) obj; + if (_id == null) + { + if (other._id != null) + { + return false; + } + } + else if (!_id.equals(other._id)) + { + return false; + } + + if (_type == null) + { + if (other._type != null) + { + return false; + } + } + else if (!_type.equals(other._type)) + { + return false; + } + + if (_store == null) + { + if (other._store != null) + { + return false; + } + } + else if (!_store.equals(other._store)) + { + return false; + } + + if (_childrenIds == null) + { + if (other._childrenIds != null) + { + return false; + } + } + else if (!_childrenIds.equals(other._childrenIds)) + { + return false; + } + + if (_attributes == null) + { + if (other._attributes != null) + { + return false; + } + } + else if (!_attributes.equals(other._attributes)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + return "ConfigurationEntry [id=" + _id + ", type=" + _type + ", attributes=" + _attributes + ", childrenIds=" + + _childrenIds + "]"; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntryStore.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntryStore.java new file mode 100644 index 0000000000..8238d147bd --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationEntryStore.java @@ -0,0 +1,98 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration; + +import java.util.UUID; + +public interface ConfigurationEntryStore +{ + /** + * Opens the store from a given location. + *

+ * If location does not exists than a new empty store is created with a single root entry + * + * @param storeLocation store location + * @throws IllegalConfigurationException if store cannot be opened in the given location + */ + void open(String storeLocation); + + /** + * Opens the store from a given location. + *

+ * If location does not exists than a new store is created either empty or from the initial store location if it is provided + * + * @param storeLocation store location + * @param initialStoreLocation initial store location + * @throws IllegalConfigurationException if store cannot be opened in the given location or initial store location does not + * exists or corrupted. + */ + void open(String storeLocation, String initialStoreLocation); + + /** + * Opens the store from a given location. + *

+ * If location does not exists than a new store is created either empty or from the initial store if it is provided + * + * @param storeLocation store location + * @param initialStore initial store + * @throws IllegalConfigurationException if store cannot be opened in the given location + */ + void open(String storeLocation, ConfigurationEntryStore initialStore); + + /** + * Returns stored root configuration entry + * + * @return root entry + */ + ConfigurationEntry getRootEntry(); + + /** + * Returns the configuration entry with a given id. + * + * @return entry with a given id or null if entry does not exists + */ + ConfigurationEntry getEntry(UUID id); + + /** + * Saves given entries in the store. + * + * @param entries entries to store + * @throws IllegalConfigurationException if save operation fails + */ + void save(ConfigurationEntry... entries); + + /** + * Removes the entries with given IDs and all their children + * + * @param entryIds IDs of entries to remove + * @return IDs of removed entries + * @throws IllegalConfigurationException if remove operation fails + */ + UUID[] remove(UUID... entryIds); + + /** + * Copies the store into the given location + * + * @param target location to copy store into + * @throws IllegalConfigurationException if store cannot be copied into given location + */ + public void copyTo(String copyLocation); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationManager.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationManager.java deleted file mode 100644 index 06402fa646..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationManager.java +++ /dev/null @@ -1,54 +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.configuration; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.registry.ApplicationRegistry; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -public class ConfigurationManager -{ - public List getConfigurationPlugins(String configurationElement, Configuration configuration) throws ConfigurationException - { - List plugins = new ArrayList(); - Map, ConfigurationPluginFactory> factories = - ApplicationRegistry.getInstance().getPluginManager().getConfigurationPlugins(); - - for (Entry, ConfigurationPluginFactory> entry : factories.entrySet()) - { - if (entry.getKey().contains(configurationElement)) - { - ConfigurationPluginFactory factory = entry.getValue(); - plugins.add(factory.newInstance(configurationElement, configuration)); - } - } - - return plugins; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationStoreFactory.java new file mode 100644 index 0000000000..dced38d260 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigurationStoreFactory.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.server.configuration; + + +public interface ConfigurationStoreFactory +{ + /** + * Returns the type of the store this factory can create + */ + public String getStoreType(); + + /** + * Creates the store instance. + */ + public ConfigurationEntryStore createStore(); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java deleted file mode 100644 index ff4e38d9f7..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java +++ /dev/null @@ -1,37 +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.configuration; - -import java.util.UUID; - -public interface ConfiguredObject, C extends ConfiguredObject> -{ - public UUID getQMFId(); - - public T getConfigType(); - - public ConfiguredObject getParent(); - - public boolean isDurable(); - - long getCreateTime(); -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObjectRecoverer.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObjectRecoverer.java new file mode 100644 index 0000000000..65d97e6db1 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObjectRecoverer.java @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration; + +import org.apache.qpid.server.model.ConfiguredObject; + +public interface ConfiguredObjectRecoverer +{ + T create(RecovererProvider recovererProvider, ConfigurationEntry entry, ConfiguredObject... parents); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfig.java deleted file mode 100644 index 0dd36fe1fe..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfig.java +++ /dev/null @@ -1,49 +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.configuration; - -public interface ConnectionConfig extends ConfiguredObject -{ - VirtualHostConfig getVirtualHost(); - - String getAddress(); - - Boolean isIncoming(); - - Boolean isSystemConnection(); - - Boolean isFederationLink(); - - String getAuthId(); - - String getRemoteProcessName(); - - Integer getRemotePID(); - - Integer getRemoteParentPID(); - - ConfigStore getConfigStore(); - - Boolean isShadow(); - - void mgmtClose(); -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfigType.java deleted file mode 100644 index 5631fda37c..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfigType.java +++ /dev/null @@ -1,146 +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.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -public final class ConnectionConfigType extends ConfigObjectType -{ - private static final List> CONNECTION_PROPERTIES = new ArrayList>(); - - public static interface ConnectionProperty extends ConfigProperty - { - } - - private abstract static class ConnectionReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements ConnectionProperty - { - public ConnectionReadWriteProperty(String name) - { - super(name); - CONNECTION_PROPERTIES.add(this); - } - } - - private abstract static class ConnectionReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements ConnectionProperty - { - public ConnectionReadOnlyProperty(String name) - { - super(name); - CONNECTION_PROPERTIES.add(this); - } - } - - public static final ConnectionReadOnlyProperty VIRTUAL_HOST_PROPERTY = new ConnectionReadOnlyProperty("virtualHost") - { - public VirtualHostConfig getValue(ConnectionConfig object) - { - return object.getVirtualHost(); - } - }; - - public static final ConnectionReadOnlyProperty ADDRESS_PROPERTY = new ConnectionReadOnlyProperty("address") - { - public String getValue(ConnectionConfig object) - { - return object.getAddress(); - } - }; - - public static final ConnectionReadOnlyProperty INCOMING_PROPERTY = new ConnectionReadOnlyProperty("incoming") - { - public Boolean getValue(ConnectionConfig object) - { - return object.isIncoming(); - } - }; - - public static final ConnectionReadOnlyProperty SYSTEM_CONNECTION_PROPERTY = new ConnectionReadOnlyProperty("systemConnection") - { - public Boolean getValue(ConnectionConfig object) - { - return object.isSystemConnection(); - } - }; - - public static final ConnectionReadOnlyProperty FEDERATION_LINK_PROPERTY = new ConnectionReadOnlyProperty("federationLink") - { - public Boolean getValue(ConnectionConfig object) - { - return object.isFederationLink(); - } - }; - - public static final ConnectionReadOnlyProperty AUTH_ID_PROPERTY = new ConnectionReadOnlyProperty("authId") - { - public String getValue(ConnectionConfig object) - { - return object.getAuthId(); - } - }; - - public static final ConnectionReadOnlyProperty REMOTE_PROCESS_NAME_PROPERTY = new ConnectionReadOnlyProperty("remoteProcessName") - { - public String getValue(ConnectionConfig object) - { - return object.getRemoteProcessName(); - } - }; - - - public static final ConnectionReadOnlyProperty REMOTE_PID_PROPERTY = new ConnectionReadOnlyProperty("remotePid") - { - public Integer getValue(ConnectionConfig object) - { - return object.getRemotePID(); - } - }; - - public static final ConnectionReadOnlyProperty REMOTE_PARENT_PID_PROPERTY = new ConnectionReadOnlyProperty("remoteParentPid") - { - public Integer getValue(ConnectionConfig object) - { - return object.getRemoteParentPID(); - } - }; - - private static final ConnectionConfigType INSTANCE = new ConnectionConfigType(); - - private ConnectionConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(CONNECTION_PROPERTIES); - } - - public static ConnectionConfigType getInstance() - { - return INSTANCE; - } - - - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java deleted file mode 100644 index 6633d93adf..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.server.configuration; - -import org.apache.qpid.server.exchange.ExchangeType; - -import java.util.Map; - - -public interface ExchangeConfig extends ConfiguredObject -{ - VirtualHostConfig getVirtualHost(); - - String getName(); - - ExchangeType getType(); - - boolean isAutoDelete(); - - ExchangeConfig getAlternateExchange(); - - Map getArguments(); - - - long getBindingCount(); - - long getBindingCountHigh(); - - long getMsgReceives(); - - long getMsgRoutes(); - - long getMsgDrops(); - - long getByteReceives(); - - long getByteRoutes(); - - long getByteDrops(); - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigType.java deleted file mode 100644 index c7744117c4..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigType.java +++ /dev/null @@ -1,115 +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.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public final class ExchangeConfigType extends ConfigObjectType -{ - private static final List> EXCHANGE_PROPERTIES = new ArrayList>(); - - public static interface ExchangeProperty extends ConfigProperty - { - } - - private abstract static class ExchangeReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements ExchangeProperty - { - public ExchangeReadWriteProperty(String name) - { - super(name); - EXCHANGE_PROPERTIES.add(this); - } - } - - private abstract static class ExchangeReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements ExchangeProperty - { - public ExchangeReadOnlyProperty(String name) - { - super(name); - EXCHANGE_PROPERTIES.add(this); - } - } - - public static final ExchangeReadOnlyProperty VIRTUAL_HOST_PROPERTY = new ExchangeReadOnlyProperty("virtualHost") - { - public VirtualHostConfig getValue(ExchangeConfig object) - { - return object.getVirtualHost(); - } - }; - - public static final ExchangeReadOnlyProperty NAME_PROPERTY = new ExchangeReadOnlyProperty("name") - { - public String getValue(ExchangeConfig object) - { - return object.getName(); - } - }; - - public static final ExchangeReadOnlyProperty AUTODELETE_PROPERTY = new ExchangeReadOnlyProperty("autodelete") - { - public Boolean getValue(ExchangeConfig object) - { - return object.isAutoDelete(); - } - }; - - - public static final ExchangeReadOnlyProperty ALTERNATE_EXCHANGE_PROPERTY = new ExchangeReadOnlyProperty("alternateExchange") - { - public ExchangeConfig getValue(ExchangeConfig object) - { - return object.getAlternateExchange(); - } - }; - - public static final ExchangeReadOnlyProperty> ARGUMENTS = new ExchangeReadOnlyProperty>("arguments") - { - public Map getValue(ExchangeConfig object) - { - return object.getArguments(); - } - }; - - private static final ExchangeConfigType INSTANCE = new ExchangeConfigType(); - - private ExchangeConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(EXCHANGE_PROPERTIES); - } - - public static ExchangeConfigType getInstance() - { - return INSTANCE; - } - - - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigurationPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigurationPlugin.java deleted file mode 100644 index bfb2de4235..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigurationPlugin.java +++ /dev/null @@ -1,29 +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.configuration; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.queue.AMQQueue; - -public interface ExchangeConfigurationPlugin -{ - ConfigurationPlugin getConfiguration(AMQQueue queue); -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/IllegalConfigurationException.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/IllegalConfigurationException.java new file mode 100644 index 0000000000..bedd470ddf --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/IllegalConfigurationException.java @@ -0,0 +1,37 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration; + +public class IllegalConfigurationException extends RuntimeException +{ + private static final long serialVersionUID = 1130064756291179812L; + + public IllegalConfigurationException(String message) + { + super(message); + } + + public IllegalConfigurationException(String message, Throwable cause) + { + super(message, cause); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfig.java deleted file mode 100644 index 2c37a94db0..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfig.java +++ /dev/null @@ -1,56 +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.configuration; - -public interface LinkConfig extends ConfiguredObject -{ - VirtualHostConfig getVirtualHost(); - - - String getTransport(); - - String getHost(); - - int getPort(); - - String getRemoteVhost(); - - String getAuthMechanism(); - - String getUsername(); - - String getPassword(); - - void close(); - - void createBridge(boolean durable, - boolean dynamic, - boolean srcIsQueue, - boolean srcIsLocal, - String src, - String dest, - String key, String tag, String excludes); - - String getState(); - - String getLastError(); -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java deleted file mode 100644 index 847cae87f5..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java +++ /dev/null @@ -1,137 +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.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -public final class LinkConfigType extends ConfigObjectType -{ - private static final List> LINK_PROPERTIES = new ArrayList>(); - - public static interface LinkProperty extends ConfigProperty - { - } - - private abstract static class LinkReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements LinkProperty - { - public LinkReadWriteProperty(String name) - { - super(name); - LINK_PROPERTIES.add(this); - } - } - - private abstract static class LinkReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements LinkProperty - { - public LinkReadOnlyProperty(String name) - { - super(name); - LINK_PROPERTIES.add(this); - } - } - - public static final LinkReadOnlyProperty VIRTUAL_HOST_PROPERTY = new LinkReadOnlyProperty("virtualHost") - { - public VirtualHostConfig getValue(LinkConfig object) - { - return object.getVirtualHost(); - } - }; - - public static final LinkReadOnlyProperty TRANSPORT_PROPERTY = new LinkReadOnlyProperty("transport") - { - public String getValue(LinkConfig object) - { - return object.getTransport(); - } - }; - - public static final LinkReadOnlyProperty HOST_PROPERTY = new LinkReadOnlyProperty("host") - { - public String getValue(LinkConfig object) - { - return object.getHost(); - } - }; - - public static final LinkReadOnlyProperty PORT_PROPERTY = new LinkReadOnlyProperty("port") - { - public Integer getValue(LinkConfig object) - { - return object.getPort(); - } - }; - - public static final LinkReadOnlyProperty REMOTE_VHOST_PROPERTY = new LinkReadOnlyProperty("remoteVhost") - { - public String getValue(LinkConfig object) - { - return object.getRemoteVhost(); - } - }; - - public static final LinkReadOnlyProperty AUTH_MECHANISM_PROPERTY = new LinkReadOnlyProperty("authMechanism") - { - public String getValue(LinkConfig object) - { - return object.getAuthMechanism(); - } - }; - - public static final LinkReadOnlyProperty USERNAME_PROPERTY = new LinkReadOnlyProperty("username") - { - public String getValue(LinkConfig object) - { - return object.getUsername(); - } - }; - - public static final LinkReadOnlyProperty PASSWORD_PROPERTY = new LinkReadOnlyProperty("password") - { - public String getValue(LinkConfig object) - { - return object.getPassword(); - } - }; - - private static final LinkConfigType INSTANCE = new LinkConfigType(); - - private LinkConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(LINK_PROPERTIES); - } - - public static LinkConfigType getInstance() - { - return INSTANCE; - } - - - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfig.java deleted file mode 100644 index 1ef5edeb51..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfig.java +++ /dev/null @@ -1,86 +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.configuration; - -import org.apache.qpid.AMQException; - -import java.util.Map; - - -public interface QueueConfig extends ConfiguredObject -{ - VirtualHostConfig getVirtualHost(); - - String getName(); - - boolean isExclusive(); - - boolean isAutoDelete(); - - ExchangeConfig getAlternateExchange(); - - Map getArguments(); - - long getReceivedMessageCount(); - - int getMessageCount(); - - long getQueueDepth(); - - int getConsumerCount(); - - int getConsumerCountHigh(); - - int getBindingCount(); - - int getBindingCountHigh(); - - ConfigStore getConfigStore(); - - long getMessageDequeueCount(); - - long getTotalEnqueueSize(); - - long getTotalDequeueSize(); - - long getByteTxnEnqueues(); - - long getByteTxnDequeues(); - - long getMsgTxnEnqueues(); - - long getMsgTxnDequeues(); - - long getPersistentByteEnqueues(); - - long getPersistentByteDequeues(); - - long getPersistentMsgEnqueues(); - - long getPersistentMsgDequeues(); - - long getUnackedMessageCount(); - - long getUnackedMessageCountHigh(); - - void purge(long request) throws AMQException; -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfigType.java deleted file mode 100644 index f958ef5350..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfigType.java +++ /dev/null @@ -1,123 +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.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public final class QueueConfigType extends ConfigObjectType -{ - private static final List> QUEUE_PROPERTIES = new ArrayList>(); - - public static interface QueueProperty extends ConfigProperty - { - } - - private abstract static class QueueReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements QueueProperty - { - public QueueReadWriteProperty(String name) - { - super(name); - QUEUE_PROPERTIES.add(this); - } - } - - private abstract static class QueueReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements QueueProperty - { - public QueueReadOnlyProperty(String name) - { - super(name); - QUEUE_PROPERTIES.add(this); - } - } - - public static final QueueReadOnlyProperty VISTUAL_HOST_PROPERTY = new QueueReadOnlyProperty("virtualHost") - { - public VirtualHostConfig getValue(QueueConfig object) - { - return object.getVirtualHost(); - } - }; - - public static final QueueReadOnlyProperty NAME_PROPERTY = new QueueReadOnlyProperty("name") - { - public String getValue(QueueConfig object) - { - return object.getName(); - } - }; - - public static final QueueReadOnlyProperty AUTODELETE_PROPERTY = new QueueReadOnlyProperty("autodelete") - { - public Boolean getValue(QueueConfig object) - { - return object.isAutoDelete(); - } - }; - - public static final QueueReadOnlyProperty EXCLUSIVE_PROPERTY = new QueueReadOnlyProperty("exclusive") - { - public Boolean getValue(QueueConfig object) - { - return object.isExclusive(); - } - }; - - public static final QueueReadOnlyProperty ALTERNATE_EXCHANGE_PROPERTY = new QueueReadOnlyProperty("alternateExchange") - { - public ExchangeConfig getValue(QueueConfig object) - { - return object.getAlternateExchange(); - } - }; - - public static final QueueReadOnlyProperty> ARGUMENTS = new QueueReadOnlyProperty>("arguments") - { - public Map getValue(QueueConfig object) - { - return object.getArguments(); - } - }; - - - private static final QueueConfigType INSTANCE = new QueueConfigType(); - - private QueueConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(QUEUE_PROPERTIES); - } - - public static QueueConfigType getInstance() - { - return INSTANCE; - } - - - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java index 8f03383777..06691d8659 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java @@ -24,11 +24,11 @@ import org.apache.commons.configuration.CompositeConfiguration; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.plugins.AbstractConfiguration; import java.util.List; -public class QueueConfiguration extends ConfigurationPlugin +public class QueueConfiguration extends AbstractConfiguration { private String _name; private VirtualHostConfiguration _vHostConfig; @@ -39,7 +39,7 @@ public class QueueConfiguration extends ConfigurationPlugin _name = name; CompositeConfiguration mungedConf = new CompositeConfiguration(); - mungedConf.addConfiguration(_vHostConfig.getConfig().subset("queues.queue." + name)); + mungedConf.addConfiguration(_vHostConfig.getConfig().subset("queues.queue." + escapeTagName(name))); mungedConf.addConfiguration(_vHostConfig.getConfig().subset("queues")); setConfiguration("virtualhosts.virtualhost.queues.queue", mungedConf); @@ -193,43 +193,4 @@ public class QueueConfiguration extends ConfigurationPlugin { return getBooleanValue("deadLetterQueues", _vHostConfig.isDeadLetterQueueEnabled()); } - - public static class QueueConfig extends ConfigurationPlugin - { - @Override - public String[] getElementsProcessed() - { - return new String[]{"name"}; - } - - public String getName() - { - return getStringValue("name"); - } - - - public void validateConfiguration() throws ConfigurationException - { - if (getConfig().isEmpty()) - { - throw new ConfigurationException("Queue section cannot be empty."); - } - - if (getName() == null) - { - throw new ConfigurationException("Queue section must have a 'name' element."); - } - - } - - - @Override - public String formatToString() - { - return "Name:"+getName(); - } - - - } - } diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/RecovererProvider.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/RecovererProvider.java new file mode 100644 index 0000000000..963d019ec3 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/RecovererProvider.java @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration; + +import org.apache.qpid.server.model.ConfiguredObject; + +public interface RecovererProvider +{ + ConfiguredObjectRecoverer getRecoverer(String type); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java deleted file mode 100644 index f9e2d93cff..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ /dev/null @@ -1,1031 +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.configuration; - -import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.TrustManagerFactory; -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.ConfigurationFactory; -import org.apache.commons.configuration.HierarchicalConfiguration; -import org.apache.commons.configuration.SystemConfiguration; -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.exchange.DefaultExchangeFactory; -import org.apache.qpid.server.protocol.AmqpProtocolVersion; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.signal.SignalHandlerTask; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; - -import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; - -public class ServerConfiguration extends ConfigurationPlugin -{ - protected static final Logger _logger = Logger.getLogger(ServerConfiguration.class); - - // Default Configuration values - public static final int DEFAULT_BUFFER_SIZE = 262144; - public static final String DEFAULT_STATUS_UPDATES = "on"; - public static final String SECURITY_CONFIG_RELOADED = "SECURITY CONFIGURATION RELOADED"; - - public static final int DEFAULT_FRAME_SIZE = 65536; - public static final int DEFAULT_PORT = 5672; - public static final int DEFAULT_SSL_PORT = 5671; - public static final long DEFAULT_HOUSEKEEPING_PERIOD = 30000L; - public static final int DEFAULT_JMXPORT_REGISTRYSERVER = 8999; - public static final int JMXPORT_CONNECTORSERVER_OFFSET = 100; - public static final int DEFAULT_HTTP_MANAGEMENT_PORT = 8080; - public static final int DEFAULT_HTTPS_MANAGEMENT_PORT = 8443; - public static final long DEFAULT_MINIMUM_ALERT_REPEAT_GAP = 30000l; - - public static final String QPID_HOME = "QPID_HOME"; - public static final String QPID_WORK = "QPID_WORK"; - public static final String LIB_DIR = "lib"; - public static final String PLUGIN_DIR = "plugins"; - public static final String CACHE_DIR = "cache"; - - private Map _virtualHosts = new HashMap(); - - private File _configFile; - private File _vhostsFile; - private String _qpidWork; - private String _qpidHome; - - // Map of environment variables to config items - private static final Map envVarMap = new HashMap(); - - // Configuration values to be read from the configuration file - //todo Move all properties to static values to ensure system testing can be performed. - public static final String MGMT_CUSTOM_REGISTRY_SOCKET = "management.custom-registry-socket"; - public static final String MGMT_JMXPORT_REGISTRYSERVER = "management.jmxport.registryServer"; - public static final String MGMT_JMXPORT_CONNECTORSERVER = "management.jmxport.connectorServer"; - public static final String SECURITY_DEFAULT_AUTH_MANAGER = "security.default-auth-manager"; - public static final String SECURITY_PORT_MAPPINGS_PORT_MAPPING_AUTH_MANAGER = "security.port-mappings.port-mapping.auth-manager"; - public static final String SECURITY_PORT_MAPPINGS_PORT_MAPPING_PORT = "security.port-mappings.port-mapping.port"; - public static final String STATUS_UPDATES = "status-updates"; - public static final String ADVANCED_LOCALE = "advanced.locale"; - public static final String CONNECTOR_AMQP10ENABLED = "connector.amqp10enabled"; - public static final String CONNECTOR_AMQP010ENABLED = "connector.amqp010enabled"; - public static final String CONNECTOR_AMQP091ENABLED = "connector.amqp091enabled"; - public static final String CONNECTOR_AMQP09ENABLED = "connector.amqp09enabled"; - public static final String CONNECTOR_AMQP08ENABLED = "connector.amqp08enabled"; - public static final String CONNECTOR_AMQP_SUPPORTED_REPLY = "connector.amqpDefaultSupportedProtocolReply"; - public static final String CONNECTOR_INCLUDE_10 = "connector.include10"; - public static final String CONNECTOR_INCLUDE_010 = "connector.include010"; - public static final String CONNECTOR_INCLUDE_091 = "connector.include091"; - public static final String CONNECTOR_INCLUDE_09 = "connector.include09"; - public static final String CONNECTOR_INCLUDE_08 = "connector.include08"; - - { - envVarMap.put("QPID_PORT", "connector.port"); - envVarMap.put("QPID_SSLPORT", "connector.ssl.port"); - envVarMap.put("QPID_JMXPORT_REGISTRYSERVER", MGMT_JMXPORT_REGISTRYSERVER); - envVarMap.put("QPID_JMXPORT_CONNECTORSERVER", MGMT_JMXPORT_CONNECTORSERVER); - envVarMap.put("QPID_FRAMESIZE", "advanced.framesize"); - envVarMap.put("QPID_MSGAUTH", "security.msg-auth"); - envVarMap.put("QPID_AUTOREGISTER", "auto_register"); - envVarMap.put("QPID_MANAGEMENTENABLED", "management.enabled"); - envVarMap.put("QPID_HTTPMANAGEMENTENABLED", "management.http.enabled"); - envVarMap.put("QPID_HTTPMANAGEMENTPORT", "management.http.port"); - envVarMap.put("QPID_HEARTBEATDELAY", "heartbeat.delay"); - envVarMap.put("QPID_HEARTBEATTIMEOUTFACTOR", "heartbeat.timeoutFactor"); - envVarMap.put("QPID_MAXIMUMMESSAGEAGE", "maximumMessageAge"); - envVarMap.put("QPID_MAXIMUMMESSAGECOUNT", "maximumMessageCount"); - envVarMap.put("QPID_MAXIMUMQUEUEDEPTH", "maximumQueueDepth"); - envVarMap.put("QPID_MAXIMUMMESSAGESIZE", "maximumMessageSize"); - envVarMap.put("QPID_MAXIMUMCHANNELCOUNT", "maximumChannelCount"); - envVarMap.put("QPID_MINIMUMALERTREPEATGAP", "minimumAlertRepeatGap"); - envVarMap.put("QPID_QUEUECAPACITY", "capacity"); - envVarMap.put("QPID_FLOWRESUMECAPACITY", "flowResumeCapacity"); - envVarMap.put("QPID_SOCKETRECEIVEBUFFER", "connector.socketReceiveBuffer"); - envVarMap.put("QPID_SOCKETWRITEBUFFER", "connector.socketWriteBuffer"); - envVarMap.put("QPID_TCPNODELAY", "connector.tcpNoDelay"); - envVarMap.put("QPID_STATUS-UPDATES", "status-updates"); - } - - /** - * Loads the given file and sets up the HUP signal handler. - * - * This will load the file and present the root level properties but will - * not perform any virtualhost configuration. - *

- * To perform this {@link #initialise()} must be called. - *

- * This has been made a two step process to allow the Plugin Manager and - * Configuration Manager to be initialised in the Application Registry. - *

- * If using this ServerConfiguration via an ApplicationRegistry there is no - * need to explicitly call {@link #initialise()} as this is done via the - * {@link ApplicationRegistry#initialise()} method. - * - * @param configurationURL - * @throws org.apache.commons.configuration.ConfigurationException - */ - public ServerConfiguration(File configurationURL) throws ConfigurationException - { - this(parseConfig(configurationURL)); - _configFile = configurationURL; - - SignalHandlerTask hupReparseTask = new SignalHandlerTask() - { - public void handle() - { - try - { - reparseConfigFileSecuritySections(); - } - catch (ConfigurationException e) - { - _logger.error("Could not reload configuration file security sections", e); - } - } - }; - - if(!hupReparseTask.register("HUP")) - { - _logger.info("Unable to register Signal HUP handler to reload security configuration."); - _logger.info("Signal HUP not supported for this OS / JVM combination - " + SignalHandlerTask.getPlatformDescription()); - } - } - - /** - * Wraps the given Commons Configuration as a ServerConfiguration. - * - * Mainly used during testing and in locations where configuration is not - * desired but the interface requires configuration. - *

- * If the given configuration has VirtualHost configuration then - * {@link #initialise()} must be called to perform the required setup. - *

- * This has been made a two step process to allow the Plugin Manager and - * Configuration Manager to be initialised in the Application Registry. - *

- * If using this ServerConfiguration via an ApplicationRegistry there is no - * need to explicitly call {@link #initialise()} as this is done via the - * {@link ApplicationRegistry#initialise()} method. - * - * @param conf - */ - public ServerConfiguration(Configuration conf) - { - setConfig(conf); - } - - /** - * Processes this configuration and setups any VirtualHosts defined in the - * configuration. - * - * This has been separated from the constructor to allow the PluginManager - * time to be created and provide plugins to the ConfigurationManager for - * processing here. - *

- * Called by {@link ApplicationRegistry#initialise()}. - *

- * NOTE: A DEFAULT ApplicationRegistry must exist when using this method - * or a new ApplicationRegistry will be created. - * - * @throws ConfigurationException - */ - public void initialise() throws ConfigurationException - { - setConfiguration("", getConfig()); - setupVirtualHosts(getConfig()); - } - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - // Support for security.jmx.access was removed when JMX access rights were incorporated into the main ACL. - // This ensure that users remove the element from their configuration file. - - if (getListValue("security.jmx.access").size() > 0) - { - String message = "Validation error : security/jmx/access is no longer a supported element within the configuration xml." - + (_configFile == null ? "" : " Configuration file : " + _configFile); - throw new ConfigurationException(message); - } - - if (getListValue("security.jmx.principal-database").size() > 0) - { - String message = "Validation error : security/jmx/principal-database is no longer a supported element within the configuration xml." - + (_configFile == null ? "" : " Configuration file : " + _configFile); - throw new ConfigurationException(message); - } - - if (getListValue("security.principal-databases.principal-database(0).class").size() > 0) - { - String message = "Validation error : security/principal-databases is no longer supported within the configuration xml." - + (_configFile == null ? "" : " Configuration file : " + _configFile); - throw new ConfigurationException(message); - } - - // QPID-3266. Tidy up housekeeping configuration option for scheduling frequency - if (contains("housekeeping.expiredMessageCheckPeriod")) - { - String message = "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod." - + (_configFile == null ? "" : " Configuration file : " + _configFile); - throw new ConfigurationException(message); - } - - String[] ports = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_PORT); - String[] authManagers = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_AUTH_MANAGER); - if (ports.length != authManagers.length) - { - throw new ConfigurationException("Validation error: Each port-mapping must have exactly one port and exactly one auth-manager."); - } - - // QPID-3517: Inconsistency in capitalisation in the SSL configuration keys used within the connector and management configuration - // sections. For the moment, continue to understand both but generate a deprecated warning if the less preferred keystore is used. - for (String key : new String[] {"management.ssl.keystorePath", - "management.ssl.keystorePassword," + - "connector.ssl.keystorePath", - "connector.ssl.keystorePassword"}) - { - if (contains(key)) - { - final String deprecatedXpath = key.replaceAll("\\.", "/"); - final String preferredXpath = deprecatedXpath.replaceAll("keystore", "keyStore"); - _logger.warn("Validation warning: " + deprecatedXpath + " is deprecated and must be replaced by " + preferredXpath - + (_configFile == null ? "" : " Configuration file : " + _configFile)); - } - } - - // QPID-3739 certType was a misleading name. - if (contains("connector.ssl.certType")) - { - _logger.warn("Validation warning: connector/ssl/certType is deprecated and must be replaced by connector/ssl/keyManagerFactoryAlgorithm" - + (_configFile == null ? "" : " Configuration file : " + _configFile)); - } - } - - /* - * Modified to enforce virtualhosts configuration in external file or main file, but not - * both, as a fix for QPID-2360 and QPID-2361. - */ - @SuppressWarnings("unchecked") - protected void setupVirtualHosts(Configuration conf) throws ConfigurationException - { - List vhostFiles = (List) conf.getList("virtualhosts"); - Configuration vhostConfig = conf.subset("virtualhosts"); - - // Only one configuration mechanism allowed - if (!vhostFiles.isEmpty() && !vhostConfig.subset("virtualhost").isEmpty()) - { - throw new ConfigurationException("Only one of external or embedded virtualhosts configuration allowed."); - } - - // We can only have one vhosts XML file included - if (vhostFiles.size() > 1) - { - throw new ConfigurationException("Only one external virtualhosts configuration file allowed, multiple filenames found."); - } - - // Virtualhost configuration object - Configuration vhostConfiguration = new HierarchicalConfiguration(); - - // Load from embedded configuration if possible - if (!vhostConfig.subset("virtualhost").isEmpty()) - { - vhostConfiguration = vhostConfig; - } - else - { - // Load from the external configuration if possible - for (String fileName : vhostFiles) - { - // Open the vhosts XML file and copy values from it to our config - _vhostsFile = new File(fileName); - if (!_vhostsFile.exists()) - { - throw new ConfigurationException("Virtualhosts file does not exist"); - } - vhostConfiguration = parseConfig(new File(fileName)); - - // save the default virtualhost name - String defaultVirtualHost = vhostConfiguration.getString("default"); - getConfig().setProperty("virtualhosts.default", defaultVirtualHost); - } - } - - // Now extract the virtual host names from the configuration object - List hosts = vhostConfiguration.getList("virtualhost.name"); - for (int j = 0; j < hosts.size(); j++) - { - String name = (String) hosts.get(j); - - // Add the virtual hosts to the server configuration - VirtualHostConfiguration virtualhost = new VirtualHostConfiguration(name, vhostConfiguration.subset("virtualhost." + name)); - _virtualHosts.put(virtualhost.getName(), virtualhost); - } - } - - private static void substituteEnvironmentVariables(Configuration conf) - { - for (Entry var : envVarMap.entrySet()) - { - String val = System.getenv(var.getKey()); - if (val != null) - { - conf.setProperty(var.getValue(), val); - } - } - } - - private static Configuration parseConfig(File file) throws ConfigurationException - { - ConfigurationFactory factory = new ConfigurationFactory(); - factory.setConfigurationFileName(file.getAbsolutePath()); - Configuration conf = factory.getConfiguration(); - - Iterator keys = conf.getKeys(); - if (!keys.hasNext()) - { - keys = null; - conf = flatConfig(file); - } - - substituteEnvironmentVariables(conf); - - return conf; - } - - /** - * Check the configuration file to see if status updates are enabled. - * - * @return true if status updates are enabled - */ - public boolean getStatusUpdatesEnabled() - { - // Retrieve the setting from configuration but default to on. - String value = getStringValue(STATUS_UPDATES, DEFAULT_STATUS_UPDATES); - - return value.equalsIgnoreCase("on"); - } - - /** - * The currently defined {@see Locale} for this broker - * - * @return the configuration defined locale - */ - public Locale getLocale() - { - String localeString = getStringValue(ADVANCED_LOCALE); - // Expecting locale of format langauge_country_variant - - // If the configuration does not have a defined locale use the JVM default - if (localeString == null) - { - return Locale.getDefault(); - } - - String[] parts = localeString.split("_"); - - Locale locale; - switch (parts.length) - { - case 1: - locale = new Locale(localeString); - break; - case 2: - locale = new Locale(parts[0], parts[1]); - break; - default: - StringBuilder variant = new StringBuilder(parts[2]); - // If we have a variant such as the Java doc suggests for Spanish - // Traditional_WIN we may end up with more than 3 parts on a - // split with '_'. So we should recombine the variant. - if (parts.length > 3) - { - for (int index = 3; index < parts.length; index++) - { - variant.append('_').append(parts[index]); - } - } - - locale = new Locale(parts[0], parts[1], variant.toString()); - } - - return locale; - } - - // Our configuration class needs to make the interpolate method - // public so it can be called below from the config method. - public static class MyConfiguration extends CompositeConfiguration - { - public String interpolate(String obj) - { - return super.interpolate(obj); - } - } - - public final static Configuration flatConfig(File file) throws ConfigurationException - { - // We have to override the interpolate methods so that - // interpolation takes place across the entirety of the - // composite configuration. Without doing this each - // configuration object only interpolates variables defined - // inside itself. - final MyConfiguration conf = new MyConfiguration(); - conf.addConfiguration(new SystemConfiguration() - { - protected String interpolate(String o) - { - return conf.interpolate(o); - } - }); - conf.addConfiguration(new XMLConfiguration(file) - { - protected String interpolate(String o) - { - return conf.interpolate(o); - } - }); - return conf; - } - - public String getConfigurationURL() - { - return _configFile == null ? "" : _configFile.getAbsolutePath(); - } - - public void reparseConfigFileSecuritySections() throws ConfigurationException - { - if (_configFile != null) - { - Configuration newConfig = parseConfig(_configFile); - setConfiguration("", newConfig); - ApplicationRegistry.getInstance().getSecurityManager().configureHostPlugins(this); - - // Reload virtualhosts from correct location - Configuration newVhosts; - if (_vhostsFile == null) - { - newVhosts = newConfig.subset("virtualhosts"); - } - else - { - newVhosts = parseConfig(_vhostsFile); - } - - VirtualHostRegistry vhostRegistry = ApplicationRegistry.getInstance().getVirtualHostRegistry(); - for (String hostName : _virtualHosts.keySet()) - { - VirtualHost vhost = vhostRegistry.getVirtualHost(hostName); - Configuration vhostConfig = newVhosts.subset("virtualhost." + hostName); - vhost.getConfiguration().setConfiguration("virtualhosts.virtualhost", vhostConfig); - vhost.getSecurityManager().configureGlobalPlugins(this); - vhost.getSecurityManager().configureHostPlugins(vhost.getConfiguration()); - } - - _logger.warn(SECURITY_CONFIG_RELOADED); - } - } - - public String getQpidWork() - { - if ( _qpidWork == null ) - { - return System.getProperty(QPID_WORK, System.getProperty("java.io.tmpdir")); - } - else - { - return _qpidWork; - } - } - - public String getQpidHome() - { - if ( _qpidHome == null ) - { - return System.getProperty(QPID_HOME); - } - else - { - return _qpidHome; - } - } - - public void setJMXPortRegistryServer(int registryServerPort) - { - getConfig().setProperty(MGMT_JMXPORT_REGISTRYSERVER, registryServerPort); - } - - public int getJMXPortRegistryServer() - { - return getIntValue(MGMT_JMXPORT_REGISTRYSERVER, DEFAULT_JMXPORT_REGISTRYSERVER); - } - - public void setJMXPortConnectorServer(int connectorServerPort) - { - getConfig().setProperty(MGMT_JMXPORT_CONNECTORSERVER, connectorServerPort); - } - - public int getJMXConnectorServerPort() - { - return getIntValue(MGMT_JMXPORT_CONNECTORSERVER, getJMXPortRegistryServer() + JMXPORT_CONNECTORSERVER_OFFSET); - } - - public boolean getUseCustomRMISocketFactory() - { - return getBooleanValue(MGMT_CUSTOM_REGISTRY_SOCKET, true); - } - - public void setUseCustomRMISocketFactory(boolean bool) - { - getConfig().setProperty(MGMT_CUSTOM_REGISTRY_SOCKET, bool); - } - - public boolean getPlatformMbeanserver() - { - return getBooleanValue("management.platform-mbeanserver", true); - } - - public boolean getHTTPManagementEnabled() - { - return getBooleanValue("management.http.enabled", true); - } - - public int getHTTPManagementPort() - { - return getIntValue("management.http.port", DEFAULT_HTTP_MANAGEMENT_PORT); - } - - public boolean getHTTPSManagementEnabled() - { - return getBooleanValue("management.https.enabled", false); - } - - public int getHTTPSManagementPort() - { - return getIntValue("management.https.port", DEFAULT_HTTPS_MANAGEMENT_PORT); - } - - public String[] getVirtualHosts() - { - return _virtualHosts.keySet().toArray(new String[_virtualHosts.size()]); - } - - public String getPluginDirectory() - { - return getStringValue("plugin-directory"); - } - - public String getCacheDirectory() - { - return getStringValue("cache-directory"); - } - - public VirtualHostConfiguration getVirtualHostConfig(String name) - { - return _virtualHosts.get(name); - } - - public void setVirtualHostConfig(VirtualHostConfiguration config) - { - _virtualHosts.put(config.getName(), config); - } - - public int getFrameSize() - { - return getIntValue("advanced.framesize", DEFAULT_FRAME_SIZE); - } - - public boolean getSynchedClocks() - { - return getBooleanValue("advanced.synced-clocks"); - } - - public boolean getMsgAuth() - { - return getBooleanValue("security.msg-auth"); - } - - public String getDefaultAuthenticationManager() - { - return getStringValue(SECURITY_DEFAULT_AUTH_MANAGER); - } - - public Map getPortAuthenticationMappings() - { - String[] ports = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_PORT); - String[] authManagers = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_AUTH_MANAGER); - - Map portMappings = new HashMap(); - for(int i = 0; i < ports.length; i++) - { - portMappings.put(Integer.valueOf(ports[i]), authManagers[i]); - } - - return portMappings; - } - - - public String getManagementKeyStorePath() - { - final String fallback = getStringValue("management.ssl.keystorePath"); - return getStringValue("management.ssl.keyStorePath", fallback); - } - - public boolean getManagementSSLEnabled() - { - return getBooleanValue("management.ssl.enabled", false); - } - - public String getManagementKeyStorePassword() - { - final String fallback = getStringValue("management.ssl.keystorePassword"); - return getStringValue("management.ssl.keyStorePassword", fallback); - } - - public boolean getQueueAutoRegister() - { - return getBooleanValue("queue.auto_register", true); - } - - public boolean getJMXManagementEnabled() - { - return getBooleanValue("management.enabled", true); - } - - public int getHeartBeatDelay() - { - return getIntValue("heartbeat.delay", 5); - } - - public double getHeartBeatTimeout() - { - return getDoubleValue("heartbeat.timeoutFactor", 2.0); - } - - public long getMaximumMessageAge() - { - return getLongValue("maximumMessageAge"); - } - - public long getMaximumMessageCount() - { - return getLongValue("maximumMessageCount"); - } - - public long getMaximumQueueDepth() - { - return getLongValue("maximumQueueDepth"); - } - - public long getMaximumMessageSize() - { - return getLongValue("maximumMessageSize"); - } - - public long getMinimumAlertRepeatGap() - { - return getLongValue("minimumAlertRepeatGap", DEFAULT_MINIMUM_ALERT_REPEAT_GAP); - } - - public long getCapacity() - { - return getLongValue("capacity"); - } - - public long getFlowResumeCapacity() - { - return getLongValue("flowResumeCapacity", getCapacity()); - } - - public int getConnectorProcessors() - { - return getIntValue("connector.processors", 4); - } - - public List getPorts() - { - return getListValue("connector.port", Collections.singletonList(DEFAULT_PORT)); - } - - public List getPortExclude10() - { - return getListValue("connector.non10port"); - } - - public List getPortExclude010() - { - return getListValue("connector.non010port"); - } - - public List getPortExclude091() - { - return getListValue("connector.non091port"); - } - - public List getPortExclude09() - { - return getListValue("connector.non09port"); - } - - public List getPortExclude08() - { - return getListValue("connector.non08port"); - } - - public List getPortInclude08() - { - return getListValue(CONNECTOR_INCLUDE_08); - } - - public List getPortInclude09() - { - return getListValue(CONNECTOR_INCLUDE_09); - } - - public List getPortInclude091() - { - return getListValue(CONNECTOR_INCLUDE_091); - } - - public List getPortInclude010() - { - return getListValue(CONNECTOR_INCLUDE_010); - } - - public List getPortInclude10() - { - return getListValue(CONNECTOR_INCLUDE_10); - } - - public String getBind() - { - return getStringValue("connector.bind", WILDCARD_ADDRESS); - } - - public int getReceiveBufferSize() - { - return getIntValue("connector.socketReceiveBuffer", DEFAULT_BUFFER_SIZE); - } - - public int getWriteBufferSize() - { - return getIntValue("connector.socketWriteBuffer", DEFAULT_BUFFER_SIZE); - } - - public boolean getTcpNoDelay() - { - return getBooleanValue("connector.tcpNoDelay", true); - } - - public boolean getEnableSSL() - { - return getBooleanValue("connector.ssl.enabled"); - } - - public boolean getSSLOnly() - { - return getBooleanValue("connector.ssl.sslOnly"); - } - - public List getSSLPorts() - { - return getListValue("connector.ssl.port", Collections.singletonList(DEFAULT_SSL_PORT)); - } - - public String getConnectorKeyStorePath() - { - final String fallback = getStringValue("connector.ssl.keystorePath"); // pre-0.13 broker supported this name. - return getStringValue("connector.ssl.keyStorePath", fallback); - } - - public String getConnectorKeyStorePassword() - { - final String fallback = getStringValue("connector.ssl.keystorePassword"); // pre-0.13 brokers supported this name. - return getStringValue("connector.ssl.keyStorePassword", fallback); - } - - public String getConnectorKeyStoreType() - { - return getStringValue("connector.ssl.keyStoreType", "JKS"); - } - - public String getConnectorKeyManagerFactoryAlgorithm() - { - final String systemFallback = KeyManagerFactory.getDefaultAlgorithm(); - // deprecated, pre-0.17 brokers supported this name. - final String fallback = getStringValue("connector.ssl.certType", systemFallback); - return getStringValue("connector.ssl.keyManagerFactoryAlgorithm", fallback); - } - - public String getConnectorTrustStorePath() - { - return getStringValue("connector.ssl.trustStorePath", null); - } - - public String getConnectorTrustStorePassword() - { - return getStringValue("connector.ssl.trustStorePassword", null); - } - - public String getConnectorTrustStoreType() - { - return getStringValue("connector.ssl.trustStoreType", "JKS"); - } - - public String getConnectorTrustManagerFactoryAlgorithm() - { - return getStringValue("connector.ssl.trustManagerFactoryAlgorithm", TrustManagerFactory.getDefaultAlgorithm()); - } - - public String getCertAlias() - { - return getStringValue("connector.ssl.certAlias", null); - } - - public boolean needClientAuth() - { - return getConfig().getBoolean("connector.ssl.needClientAuth", false); - } - - public boolean wantClientAuth() - { - return getConfig().getBoolean("connector.ssl.wantClientAuth", false); - } - - public String getDefaultVirtualHost() - { - return getStringValue("virtualhosts.default"); - } - - public void setDefaultVirtualHost(String vhost) - { - getConfig().setProperty("virtualhosts.default", vhost); - } - - public void setHousekeepingCheckPeriod(long value) - { - getConfig().setProperty("housekeeping.checkPeriod", value); - } - - public long getHousekeepingCheckPeriod() - { - return getLongValue("housekeeping.checkPeriod", DEFAULT_HOUSEKEEPING_PERIOD); - } - - public long getStatisticsSamplePeriod() - { - return getConfig().getLong("statistics.sample.period", 5000L); - } - - public boolean isStatisticsGenerationBrokerEnabled() - { - return getConfig().getBoolean("statistics.generation.broker", false); - } - - public boolean isStatisticsGenerationVirtualhostsEnabled() - { - return getConfig().getBoolean("statistics.generation.virtualhosts", false); - } - - public boolean isStatisticsGenerationConnectionsEnabled() - { - return getConfig().getBoolean("statistics.generation.connections", false); - } - - public long getStatisticsReportingPeriod() - { - return getConfig().getLong("statistics.reporting.period", 0L); - } - - public boolean isStatisticsReportResetEnabled() - { - return getConfig().getBoolean("statistics.reporting.reset", false); - } - - public int getMaxChannelCount() - { - return getIntValue("maximumChannelCount", 256); - } - - /** - * List of Broker features that have been disabled within configuration. Disabled - * features won't be advertised to the clients on connection. - * - * @return list of disabled features, or empty list if no features are disabled. - */ - public List getDisabledFeatures() - { - final List disabledFeatures = getListValue("disabledFeatures", Collections.emptyList()); - return disabledFeatures; - } - - public boolean getManagementRightsInferAllAccess() - { - return getBooleanValue("management.managementRightsInferAllAccess", true); - } - - public int getMaxDeliveryCount() - { - return getConfig().getInt("maximumDeliveryCount", 0); - } - - /** - * Check if dead letter queue delivery is enabled, defaults to disabled if not set. - */ - public boolean isDeadLetterQueueEnabled() - { - return getConfig().getBoolean("deadLetterQueues", false); - } - - /** - * String to affix to end of queue name when generating an alternate exchange for DLQ purposes. - */ - public String getDeadLetterExchangeSuffix() - { - return getConfig().getString("deadLetterExchangeSuffix", DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); - } - - /** - * String to affix to end of queue name when generating a queue for DLQ purposes. - */ - public String getDeadLetterQueueSuffix() - { - return getConfig().getString("deadLetterQueueSuffix", AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); - } - - public boolean isAmqp10enabled() - { - return getConfig().getBoolean(CONNECTOR_AMQP10ENABLED, true); - } - - public boolean isAmqp010enabled() - { - return getConfig().getBoolean(CONNECTOR_AMQP010ENABLED, true); - } - - public boolean isAmqp091enabled() - { - return getConfig().getBoolean(CONNECTOR_AMQP091ENABLED, true); - } - - public boolean isAmqp09enabled() - { - return getConfig().getBoolean(CONNECTOR_AMQP09ENABLED, true); - } - - public boolean isAmqp08enabled() - { - return getConfig().getBoolean(CONNECTOR_AMQP08ENABLED, true); - } - - /** - * Returns the configured default reply to an unsupported AMQP protocol initiation, or null if there is none - */ - public AmqpProtocolVersion getDefaultSupportedProtocolReply() - { - String reply = getConfig().getString(CONNECTOR_AMQP_SUPPORTED_REPLY, null); - - return reply == null ? null : AmqpProtocolVersion.valueOf(reply); - } - - public void setQpidWork(String path) - { - _qpidWork = path; - } - - public void setQpidHome(String path) - { - _qpidHome = path; - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java deleted file mode 100644 index 51dcc38c47..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.configuration; - -import java.net.InetSocketAddress; -import org.apache.qpid.transport.NetworkTransportConfiguration; - -public class ServerNetworkTransportConfiguration implements NetworkTransportConfiguration -{ - private final ServerConfiguration _serverConfig; - private final String _transport; - private InetSocketAddress _address; - - public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig, - final InetSocketAddress address, - final String transport) - { - _serverConfig = serverConfig; - _address = address; - _transport = transport; - } - - public Boolean getTcpNoDelay() - { - return _serverConfig.getTcpNoDelay(); - } - - public Integer getSendBufferSize() - { - return _serverConfig.getWriteBufferSize(); - } - - public Integer getReceiveBufferSize() - { - return _serverConfig.getReceiveBufferSize(); - } - - public Integer getPort() - { - return _address.getPort(); - } - - public String getHost() - { - return _address.getHostName(); - } - - public String getTransport() - { - return _transport; - } - - public Integer getConnectorProcessors() - { - return _serverConfig.getConnectorProcessors(); - } - - public InetSocketAddress getAddress() - { - return _address; - } - - public boolean needClientAuth() - { - return _serverConfig.needClientAuth(); - } - - @Override - public boolean wantClientAuth() - { - return _serverConfig.wantClientAuth(); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfig.java deleted file mode 100644 index 8fef642eff..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfig.java +++ /dev/null @@ -1,55 +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.configuration; - -import org.apache.qpid.AMQException; - -public interface SessionConfig extends ConfiguredObject -{ - VirtualHostConfig getVirtualHost(); - - String getSessionName(); - - int getChannel(); - - ConnectionConfig getConnectionConfig(); - - boolean isAttached(); - - long getDetachedLifespan(); - - Long getExpiryTime(); - - Long getMaxClientRate(); - - Long getTxnStarts(); - - Long getTxnCommits(); - - Long getTxnRejects(); - - Long getTxnCount(); - - boolean isTransactional(); - - void mgmtClose() throws AMQException; -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfigType.java deleted file mode 100644 index 1685cfab60..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfigType.java +++ /dev/null @@ -1,137 +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.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -public final class SessionConfigType extends ConfigObjectType -{ - private static final List> SESSION_PROPERTIES = new ArrayList>(); - - public static interface SessionProperty extends ConfigProperty - { - } - - private abstract static class SessionReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements SessionProperty - { - public SessionReadWriteProperty(String name) - { - super(name); - SESSION_PROPERTIES.add(this); - } - } - - private abstract static class SessionReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements SessionProperty - { - public SessionReadOnlyProperty(String name) - { - super(name); - SESSION_PROPERTIES.add(this); - } - } - - public static final SessionReadOnlyProperty VIRTUAL_HOST_PROPERTY = new SessionReadOnlyProperty("virtualHost") - { - public VirtualHostConfig getValue(SessionConfig object) - { - return object.getVirtualHost(); - } - }; - - public static final SessionReadOnlyProperty NAME_PROPERTY = new SessionReadOnlyProperty("name") - { - public String getValue(SessionConfig object) - { - return object.getSessionName(); - } - }; - - public static final SessionReadOnlyProperty CHANNEL_ID_PROPERTY = new SessionReadOnlyProperty("channelId") - { - public Integer getValue(SessionConfig object) - { - return object.getChannel(); - } - }; - - public static final SessionReadOnlyProperty CONNECTION_PROPERTY = new SessionReadOnlyProperty("connection") - { - public ConnectionConfig getValue(SessionConfig object) - { - return object.getConnectionConfig(); - } - }; - - public static final SessionReadOnlyProperty ATTACHED_PROPERTY = new SessionReadOnlyProperty("attached") - { - public Boolean getValue(SessionConfig object) - { - return object.isAttached(); - } - }; - - public static final SessionReadOnlyProperty DETACHED_LIFESPAN_PROPERTY = new SessionReadOnlyProperty("detachedLifespan") - { - public Long getValue(SessionConfig object) - { - return object.getDetachedLifespan(); - } - }; - - public static final SessionReadOnlyProperty EXPIRE_TIME_PROPERTY = new SessionReadOnlyProperty("expireTime") - { - public Long getValue(SessionConfig object) - { - return object.getExpiryTime(); - } - }; - - public static final SessionReadOnlyProperty MAX_CLIENT_RATE_PROPERTY = new SessionReadOnlyProperty("maxClientRate") - { - public Long getValue(SessionConfig object) - { - return object.getMaxClientRate(); - } - }; - - private static final SessionConfigType INSTANCE = new SessionConfigType(); - - private SessionConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(SESSION_PROPERTIES); - } - - public static SessionConfigType getInstance() - { - return INSTANCE; - } - - - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfig.java deleted file mode 100644 index b101d70553..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfig.java +++ /dev/null @@ -1,47 +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.configuration; - -import java.util.Map; - - -public interface SubscriptionConfig extends ConfiguredObject -{ - - SessionConfig getSessionConfig(); - - QueueConfig getQueue(); - - String getName(); - - Map getArguments(); - - String getCreditMode(); - - boolean isBrowsing(); - - boolean isExclusive(); - - boolean isExplicitAcknowledge(); - - Long getDelivered(); -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfigType.java deleted file mode 100644 index 7b7848dd87..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfigType.java +++ /dev/null @@ -1,140 +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.configuration; - - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -public final class SubscriptionConfigType extends ConfigObjectType -{ - private static final List> SUBSCRIPTION_PROPERTIES = new ArrayList>(); - - public static interface SubscriptionProperty extends ConfigProperty - { - } - - private abstract static class SubscriptionReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements SubscriptionProperty - { - public SubscriptionReadWriteProperty(String name) - { - super(name); - SUBSCRIPTION_PROPERTIES.add(this); - } - } - - private abstract static class SubscriptionReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements SubscriptionProperty - { - public SubscriptionReadOnlyProperty(String name) - { - super(name); - SUBSCRIPTION_PROPERTIES.add(this); - } - } - - public static final SubscriptionReadOnlyProperty SESSION_PROPERTY = new SubscriptionReadOnlyProperty("session") - { - public SessionConfig getValue(SubscriptionConfig object) - { - return object.getSessionConfig(); - } - }; - - public static final SubscriptionReadOnlyProperty QUEUE_PROPERTY = new SubscriptionReadOnlyProperty("queue") - { - public QueueConfig getValue(SubscriptionConfig object) - { - return object.getQueue(); - } - }; - - public static final SubscriptionReadOnlyProperty NAME_PROPERTY = new SubscriptionReadOnlyProperty("name") - { - public String getValue(SubscriptionConfig object) - { - return object.getName(); - } - }; - - public static final SubscriptionReadOnlyProperty> ARGUMENTS = new SubscriptionReadOnlyProperty>("arguments") - { - public Map getValue(SubscriptionConfig object) - { - return object.getArguments(); - } - }; - - public static final SubscriptionReadOnlyProperty CREDIT_MODE_PROPERTY = new SubscriptionReadOnlyProperty("creditMode") - { - public String getValue(SubscriptionConfig object) - { - return object.getCreditMode(); - } - }; - - public static final SubscriptionReadOnlyProperty BROWSING_PROPERTY = new SubscriptionReadOnlyProperty("browsing") - { - public Boolean getValue(SubscriptionConfig object) - { - return object.isBrowsing(); - } - }; - - public static final SubscriptionReadOnlyProperty EXCLUSIVE_PROPERTY = new SubscriptionReadOnlyProperty("exclusive") - { - public Boolean getValue(SubscriptionConfig object) - { - return object.isExclusive(); - } - }; - - public static final SubscriptionReadOnlyProperty EXPLICIT_ACK_PROPERTY = new SubscriptionReadOnlyProperty("explicitAck") - { - public Boolean getValue(SubscriptionConfig object) - { - return object.isExplicitAcknowledge(); - } - }; - - private static final SubscriptionConfigType INSTANCE = new SubscriptionConfigType(); - - private SubscriptionConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(SUBSCRIPTION_PROPERTIES); - } - - - public static SubscriptionConfigType getInstance() - { - return INSTANCE; - } - - - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfig.java deleted file mode 100644 index 8a9029fbfd..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfig.java +++ /dev/null @@ -1,42 +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.configuration; - -public interface SystemConfig extends ConfiguredObject -{ - String getName(); - - String getOperatingSystemName(); - - String getNodeName(); - - - String getOSRelease(); - - String getOSVersion(); - - String getOSArchitecture(); - - void addBroker(BrokerConfig broker); - - void removeBroker(BrokerConfig broker); -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java deleted file mode 100644 index 80c2e8b2f1..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java +++ /dev/null @@ -1,137 +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.configuration; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public class SystemConfigImpl implements SystemConfig -{ - private static final String OS_NAME = System.getProperty("os.name"); - private static final String OS_ARCH = System.getProperty("os.arch"); - private static final String OS_VERSION = System.getProperty("os.version"); - - private final UUID _qmfId; - private String _name; - - private final String _host; - - private final Map _brokers = new ConcurrentHashMap(); - - private final long _createTime = System.currentTimeMillis(); - private final ConfigStore _store; - - public SystemConfigImpl(ConfigStore store) - { - this(store.createId(), store); - } - - public SystemConfigImpl(UUID qmfId, ConfigStore store) - { - _qmfId = qmfId; - _store = store; - String host; - try - { - InetAddress addr = InetAddress.getLocalHost(); - host = addr.getHostName(); - } - catch (UnknownHostException e) - { - host="localhost"; - } - _host = host; - } - - public String getName() - { - return _name; - } - - public String getOperatingSystemName() - { - return OS_NAME; - } - - public String getNodeName() - { - return _host; - } - - public String getOSRelease() - { - return OS_VERSION; - } - - public String getOSVersion() - { - return ""; - } - - public String getOSArchitecture() - { - return OS_ARCH; - } - - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public SystemConfigType getConfigType() - { - return SystemConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return null; - } - - public boolean isDurable() - { - return false; - } - - public void addBroker(final BrokerConfig broker) - { - broker.setSystem(this); - _store.addConfiguredObject(broker); - _brokers.put(broker.getQMFId(), broker); - } - - public void removeBroker(final BrokerConfig broker) - { - _brokers.remove(broker.getQMFId()); - _store.removeConfiguredObject(broker); - } - - public long getCreateTime() - { - return _createTime; - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java deleted file mode 100644 index 4a383cce7a..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.server.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.UUID; - -public final class SystemConfigType extends ConfigObjectType -{ - private static final List> SYSTEM_PROPERTIES = new ArrayList>(); - - public static interface SystemProperty extends ConfigProperty - { - } - - private abstract static class SystemReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements SystemProperty - { - public SystemReadWriteProperty(String name) - { - super(name); - SYSTEM_PROPERTIES.add(this); - } - } - - private abstract static class SystemReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements SystemProperty - { - public SystemReadOnlyProperty(String name) - { - super(name); - SYSTEM_PROPERTIES.add(this); - } - } - - public static final SystemReadOnlyProperty NAME_PROPERTY = new SystemReadOnlyProperty("name") - { - public String getValue(SystemConfig object) - { - return object.getName(); - } - }; - - public static final SystemReadOnlyProperty ID_PROPERTY = new SystemReadOnlyProperty("id") - { - public UUID getValue(SystemConfig object) - { - return object.getQMFId(); - } - }; - - public static final SystemReadOnlyProperty OS_NAME_PROPERTY = new SystemReadOnlyProperty("osName") - { - public String getValue(SystemConfig object) - { - return object.getOperatingSystemName(); - } - }; - - public static final SystemReadOnlyProperty NODE_NAME_PROPERTY = new SystemReadOnlyProperty("nodeName") - { - public String getValue(SystemConfig object) - { - return object.getNodeName(); - } - }; - - public static final SystemReadOnlyProperty RELEASE_PROPERTY = new SystemReadOnlyProperty("release") - { - public String getValue(SystemConfig object) - { - return object.getOSRelease(); - } - }; - - public static final SystemReadOnlyProperty VERSION_PROPERTY = new SystemReadOnlyProperty("version") - { - public String getValue(SystemConfig object) - { - return object.getOSVersion(); - } - }; - - public static final SystemReadOnlyProperty MACHINE_PROPERTY = new SystemReadOnlyProperty("machine") - { - public String getValue(SystemConfig object) - { - return object.getOSArchitecture(); - } - }; - - private static final SystemConfigType INSTANCE = new SystemConfigType(); - - private SystemConfigType() - { - } - - public Collection> getProperties() - { - return Collections.unmodifiableList(SYSTEM_PROPERTIES); - } - - - - public static SystemConfigType getInstance() - { - return INSTANCE; - } - - - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java deleted file mode 100644 index aaa1766489..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java +++ /dev/null @@ -1,78 +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.configuration; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; - -public class TopicConfig extends ConfigurationPlugin -{ - public TopicConfig() - { - setConfig(new PropertiesConfiguration()); - } - - @Override - public String[] getElementsProcessed() - { - return new String[]{"name", "subscriptionName"}; - } - - public String getName() - { - // If we don't have a specific topic then this config is for all topics. - return getStringValue("name", "#"); - } - - public String getSubscriptionName() - { - return getStringValue("subscriptionName"); - } - - public void validateConfiguration() throws ConfigurationException - { - if (getConfig().isEmpty()) - { - throw new ConfigurationException("Topic section cannot be empty."); - } - - if (getStringValue("name") == null && getSubscriptionName() == null) - { - throw new ConfigurationException("Topic section must have a 'name' or 'subscriptionName' element."); - } - - } - - - @Override - public String formatToString() - { - String response = "Topic:"+getName(); - if (getSubscriptionName() != null) - { - response += ", SubscriptionName:"+getSubscriptionName(); - } - - return response; - } -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfiguration.java deleted file mode 100644 index feafd3de1d..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfiguration.java +++ /dev/null @@ -1,270 +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.configuration; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.exchange.TopicExchange; -import org.apache.qpid.server.queue.AMQQueue; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -public class TopicConfiguration extends ConfigurationPlugin implements ExchangeConfigurationPlugin -{ - public static final ConfigurationPluginFactory FACTORY = new TopicConfigurationFactory(); - - private static final String VIRTUALHOSTS_VIRTUALHOST_TOPICS = "virtualhosts.virtualhost.topics"; - - public static class TopicConfigurationFactory implements ConfigurationPluginFactory - { - - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - TopicConfiguration topicsConfig = new TopicConfiguration(); - topicsConfig.setConfiguration(path, config); - return topicsConfig; - } - - public List getParentPaths() - { - return Arrays.asList(VIRTUALHOSTS_VIRTUALHOST_TOPICS); - } - } - - private Map _topics = new HashMap(); - private Map> _subscriptions = new HashMap>(); - - public String[] getElementsProcessed() - { - return new String[]{"topic"}; - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - if (getConfig().isEmpty()) - { - throw new ConfigurationException("Topics section cannot be empty."); - } - - int topics = getConfig().getList("topic.name").size() + - getConfig().getList("topic.subscriptionName").size(); - - for (int index = 0; index < topics; index++) - { - Configuration topicSubset = getConfig().subset("topic(" + index + ")"); - - // This will occur when we have a subscriptionName that is bound to a - // topic. - if (topicSubset.isEmpty()) - { - break; - } - - TopicConfig topic = new TopicConfig(); - - topic.setConfiguration(VIRTUALHOSTS_VIRTUALHOST_TOPICS + ".topic", topicSubset ); - - String name = getConfig().getString("topic(" + index + ").name"); - String subscriptionName = getConfig().getString("topic(" + index + ").subscriptionName"); - - // Record config if subscriptionName is there - if (subscriptionName != null) - { - processSubscription(subscriptionName, topic); - } - else - { - // Otherwise record config as topic if we have the name - if (name != null) - { - processTopic(name, topic); - } - } - } - } - - /** - * @param name - * @param topic - * - * @throws org.apache.commons.configuration.ConfigurationException - * - */ - private void processTopic(String name, TopicConfig topic) throws ConfigurationException - { - if (_topics.containsKey(name)) - { - throw new ConfigurationException("Topics section cannot contain two entries for the same topic."); - } - else - { - _topics.put(name, topic); - } - } - - - private void processSubscription(String name, TopicConfig topic) throws ConfigurationException - { - Map topics; - if (_subscriptions.containsKey(name)) - { - topics = _subscriptions.get(name); - - if (topics.containsKey(topic.getName())) - { - throw new ConfigurationException("Subcription cannot contain two entries for the same topic."); - } - } - else - { - topics = new HashMap(); - } - - topics.put(topic.getName(),topic); - _subscriptions.put(name, topics); - - } - - @Override - public String formatToString() - { - return "Topics:" + _topics + ", Subscriptions:" + _subscriptions; - } - - /** - * This processes the given queue and apply configuration in the following - * order: - * - * Global Topic Values -> Topic Values -> Subscription Values - * - * @param queue - * - * @return - */ - public ConfigurationPlugin getConfiguration(AMQQueue queue) - { - //Create config with global topic configuration - TopicConfig config = new TopicConfig(); - - // Add global topic configuration - config.addConfiguration(this); - - // Process Topic Bindings as these are more generic than subscriptions - List boundToTopics = new LinkedList(); - - //Merge the configuration in the order that they are bound - for (Binding binding : queue.getBindings()) - { - if (binding.getExchange().getType().equals(TopicExchange.TYPE)) - { - // Identify topic for the binding key - TopicConfig topicConfig = getTopicConfigForRoutingKey(binding.getBindingKey()); - if (topicConfig != null) - { - boundToTopics.add(topicConfig); - } - } - } - - // If the Queue is bound to a number of topics then only use the global - // topic configuration. - // todo - What does it mean in terms of configuration to be bound to a - // number of topics? Do we try and merge? - // YES - right thing to do would be to merge from generic to specific. - // Means we need to be able to get an ordered list of topics for this - // binding. - if (boundToTopics.size() == 1) - { - config.addConfiguration(boundToTopics.get(0)); - } - - // If we have a subscription then attempt to look it up. - String subscriptionName = queue.getName(); - - // Apply subscription configurations - if (_subscriptions.containsKey(subscriptionName)) - { - - //Get all the Configuration that this subscription is bound to. - Map topics = _subscriptions.get(subscriptionName); - - TopicConfig subscriptionSpecificConfig = null; - - // See if we have a TopicConfig in topics for a topic we are bound to. - for (Binding binding : queue.getBindings()) - { - if (binding.getExchange().getType().equals(TopicExchange.TYPE)) - { - //todo - What does it mean to have multiple matches? - // Take the first match we get - if (subscriptionSpecificConfig == null) - { - // lookup the binding to see if we have a match in the subscription configs - subscriptionSpecificConfig = topics.get(binding.getBindingKey()); - } - } - } - - //todo we don't account for wild cards here. only explicit matching and all subscriptions - if (subscriptionSpecificConfig == null) - { - // lookup the binding to see if we have a match in the subscription configs - subscriptionSpecificConfig = topics.get("#"); - } - - // Apply subscription specific config. - if (subscriptionSpecificConfig != null) - { - config.addConfiguration(subscriptionSpecificConfig); - } - } - return config; - } - - /** - * This method should perform the same heuristics as the TopicExchange - * to attempt to identify a piece of configuration for the give routingKey. - * - * i.e. If we have 'stocks.*' defined in the config - * and we bind 'stocks.appl' then we should return the 'stocks.*' - * configuration. - * - * @param routingkey the key to lookup - * - * @return the TopicConfig if found. - */ - private TopicConfig getTopicConfigForRoutingKey(String routingkey) - { - //todo actually perform TopicExchange style lookup not just straight - // lookup as we are just now. - return _topics.get(routingkey); - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java deleted file mode 100644 index b96ddc56c6..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java +++ /dev/null @@ -1,32 +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.configuration; - -public interface VirtualHostConfig extends ConfiguredObject -{ - String getName(); - - BrokerConfig getBroker(); - - String getFederationTag(); - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfigType.java deleted file mode 100644 index 16e08e3934..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfigType.java +++ /dev/null @@ -1,99 +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.configuration; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -public class VirtualHostConfigType extends ConfigObjectType -{ - private static final List> VIRTUAL_HOST_PROPERTIES = new ArrayList>(); - private static final VirtualHostConfigType INSTANCE = new VirtualHostConfigType(); -public static interface VirtualHostProperty extends ConfigProperty - { - } - - private abstract static class VirtualHostReadWriteProperty extends ConfigProperty.ReadWriteConfigProperty implements VirtualHostProperty - { - public VirtualHostReadWriteProperty(String name) - { - super(name); - VIRTUAL_HOST_PROPERTIES.add(this); - } - } - - private abstract static class VirtualHostReadOnlyProperty extends ConfigProperty.ReadOnlyConfigProperty implements VirtualHostProperty - { - public VirtualHostReadOnlyProperty(String name) - { - super(name); - VIRTUAL_HOST_PROPERTIES.add(this); - } - } - - - public static final VirtualHostReadOnlyProperty NAME_PROPERTY = new VirtualHostReadOnlyProperty("name") - { - public String getValue(VirtualHostConfig object) - { - return object.getName(); - } - }; - - - public static final VirtualHostReadOnlyProperty BROKER_PROPERTY = new VirtualHostReadOnlyProperty("broker") - { - public BrokerConfig getValue(VirtualHostConfig object) - { - return object.getBroker(); - } - }; - - public static final VirtualHostReadOnlyProperty FEDERATION_TAG_PROPERTY = new VirtualHostReadOnlyProperty("federationTag") - { - public String getValue(VirtualHostConfig object) - { - return object.getFederationTag(); - } - }; - - - - public Collection> getProperties() - { - return Collections.unmodifiableList(VIRTUAL_HOST_PROPERTIES); - } - - - private VirtualHostConfigType() - { - } - - public static VirtualHostConfigType getInstance() - { - return INSTANCE; - } - - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java index e557085631..eada676b65 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java @@ -23,35 +23,66 @@ package org.apache.qpid.server.configuration; import org.apache.commons.configuration.CompositeConfiguration; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; - -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; + +import org.apache.qpid.server.configuration.plugins.AbstractConfiguration; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.store.MemoryMessageStore; -import java.util.ArrayList; -import java.util.Arrays; +import java.io.File; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -public class VirtualHostConfiguration extends ConfigurationPlugin +public class VirtualHostConfiguration extends AbstractConfiguration { private final String _name; private final Map _queues = new HashMap(); private final Map _exchanges = new HashMap(); + private final Broker _broker; + private final long _defaultHouseKeepingCheckPeriod; - public VirtualHostConfiguration(String name, Configuration config) throws ConfigurationException + public VirtualHostConfiguration(String name, Configuration config, Broker broker) throws ConfigurationException { _name = name; + _broker = broker; + + // store value of this attribute for running life of virtual host since updating of this value has no run-time effect + _defaultHouseKeepingCheckPeriod = ((Number)_broker.getAttribute(Broker.HOUSEKEEPING_CHECK_PERIOD)).longValue(); setConfiguration(config); } + public VirtualHostConfiguration(String name, File configurationFile, Broker broker) throws ConfigurationException + { + this(name, loadConfiguration(name, configurationFile), broker); + } + + private static Configuration loadConfiguration(String name, File configurationFile) throws ConfigurationException + { + Configuration configuration = null; + if (configurationFile == null) + { + throw new IllegalConfigurationException("Virtualhost configuration file must be supplied!"); + } + else + { + Configuration virtualHostConfig = XmlConfigurationUtilities.parseConfig(configurationFile, null); + + // check if it is an old virtual host configuration file which has an element of the same name as virtual host + Configuration config = virtualHostConfig.subset("virtualhost." + XmlConfigurationUtilities.escapeTagName(name)); + if (config.isEmpty()) + { + // assume it is a new configuration which does not have an element of the same name as the virtual host + configuration = virtualHostConfig; + } + else + { + configuration = config; + } + } + return configuration; + } + /** * Apply the given configuration to this VirtualHostConfiguration * @@ -89,12 +120,7 @@ public class VirtualHostConfiguration extends ConfigurationPlugin public long getHousekeepingCheckPeriod() { - return getLongValue("housekeeping.checkPeriod", ApplicationRegistry.getInstance().getConfiguration().getHousekeepingCheckPeriod()); - } - - public List getCustomExchanges() - { - return getListValue("custom-exchanges.class-name"); + return getLongValue("housekeeping.checkPeriod", _defaultHouseKeepingCheckPeriod); } public Configuration getStoreConfiguration() @@ -149,138 +175,39 @@ public class VirtualHostConfiguration extends ConfigurationPlugin } } - public ConfigurationPlugin getQueueConfiguration(AMQQueue queue) - { - VirtualHostConfiguration hostConfig = queue.getVirtualHost().getConfiguration(); - - // First check if we have a named queue configuration (the easy case) - if (Arrays.asList(hostConfig.getQueueNames()).contains(queue.getName())) - { - return null; - } - - // We don't have an explicit queue config we must find out what we need. - ArrayList bindings = new ArrayList(queue.getBindings()); - - List exchangeClasses = new ArrayList(bindings.size()); - - //Remove default exchange - for (int index = 0; index < bindings.size(); index++) - { - // Ignore the DEFAULT Exchange binding - if (bindings.get(index).getExchange().getNameShortString().equals(ExchangeDefaults.DEFAULT_EXCHANGE_NAME)) - { - bindings.remove(index); - } - else - { - exchangeClasses.add(bindings.get(index).getExchange().getType().getName()); - - if (exchangeClasses.size() > 1) - { - // If we have more than 1 class of exchange then we can only use the global queue configuration. - // and this will be returned from the default getQueueConfiguration - return null; - } - } - } - - // If we are just bound the the default exchange then use the default. - if (bindings.isEmpty()) - { - return null; - } - - // If we are bound to only one type of exchange then we are going - // to have to resolve the configuration for that exchange. - - String exchangeName = bindings.get(0).getExchange().getType().getName().toString(); - - // Lookup a Configuration handler for this Exchange. - - // Build the expected class name. sConfiguration - // i.e. TopicConfiguration or HeadersConfiguration - String exchangeClass = "org.apache.qpid.server.configuration." - + exchangeName.substring(0, 1).toUpperCase() - + exchangeName.substring(1) + "Configuration"; - - ExchangeConfigurationPlugin exchangeConfiguration - = (ExchangeConfigurationPlugin) queue.getVirtualHost().getConfiguration().getConfiguration(exchangeClass); - - // now need to perform the queue-topic-topics-queues magic. - // So make a new ConfigurationObject that will hold all the configuration for this queue. - ConfigurationPlugin queueConfig = new QueueConfiguration.QueueConfig(); - - // Initialise the queue with any Global values we may have - PropertiesConfiguration newQueueConfig = new PropertiesConfiguration(); - newQueueConfig.setProperty("name", queue.getName()); - - try - { - //Set the queue name - CompositeConfiguration mungedConf = new CompositeConfiguration(); - //Set the queue name - mungedConf.addConfiguration(newQueueConfig); - //Set the global queue configuration - mungedConf.addConfiguration(getConfig().subset("queues")); - - // Set configuration - queueConfig.setConfiguration("virtualhosts.virtualhost.queues", mungedConf); - } - catch (ConfigurationException e) - { - // This will not occur as queues only require a name. - _logger.error("QueueConfiguration requirements have changed."); - } - - // Merge any configuration the Exchange wishes to apply - if (exchangeConfiguration != null) - { - queueConfig.addConfiguration(exchangeConfiguration.getConfiguration(queue)); - } - - //Finally merge in any specific queue configuration we have. - if (_queues.containsKey(queue.getName())) - { - queueConfig.addConfiguration(_queues.get(queue.getName())); - } - - return queueConfig; - } - public int getMaximumMessageAge() { - return getIntValue("queues.maximumMessageAge"); + return getIntValue("queues.maximumMessageAge", getBrokerAttributeAsInt(Broker.ALERT_THRESHOLD_MESSAGE_AGE)); } public Long getMaximumQueueDepth() { - return getLongValue("queues.maximumQueueDepth"); + return getLongValue("queues.maximumQueueDepth", getBrokerAttributeAsLong(Broker.ALERT_THRESHOLD_QUEUE_DEPTH)); } public Long getMaximumMessageSize() { - return getLongValue("queues.maximumMessageSize"); + return getLongValue("queues.maximumMessageSize", getBrokerAttributeAsLong(Broker.ALERT_THRESHOLD_MESSAGE_SIZE)); } public Long getMaximumMessageCount() { - return getLongValue("queues.maximumMessageCount"); + return getLongValue("queues.maximumMessageCount", getBrokerAttributeAsLong(Broker.ALERT_THRESHOLD_MESSAGE_COUNT)); } public Long getMinimumAlertRepeatGap() { - return getLongValue("queues.minimumAlertRepeatGap", ApplicationRegistry.getInstance().getConfiguration().getMinimumAlertRepeatGap()); + return getLongValue("queues.minimumAlertRepeatGap", getBrokerAttributeAsLong(Broker.ALERT_REPEAT_GAP)); } public long getCapacity() { - return getLongValue("queues.capacity"); + return getLongValue("queues.capacity", getBrokerAttributeAsLong(Broker.FLOW_CONTROL_SIZE_BYTES)); } public long getFlowResumeCapacity() { - return getLongValue("queues.flowResumeCapacity", getCapacity()); + return getLongValue("queues.flowResumeCapacity", getBrokerAttributeAsLong(Broker.FLOW_CONTROL_RESUME_SIZE_BYTES)); } public String[] getElementsProcessed() @@ -336,7 +263,7 @@ public class VirtualHostConfiguration extends ConfigurationPlugin public int getMaxDeliveryCount() { - return getIntValue("queues.maximumDeliveryCount", ApplicationRegistry.getInstance().getConfiguration().getMaxDeliveryCount()); + return getIntValue("queues.maximumDeliveryCount", getBrokerAttributeAsInt(Broker.MAXIMUM_DELIVERY_ATTEMPTS)); } /** @@ -344,7 +271,25 @@ public class VirtualHostConfiguration extends ConfigurationPlugin */ public boolean isDeadLetterQueueEnabled() { - return getBooleanValue("queues.deadLetterQueues", ApplicationRegistry.getInstance().getConfiguration().isDeadLetterQueueEnabled()); + return getBooleanValue("queues.deadLetterQueues", getBrokerAttributeAsBoolean(Broker.DEAD_LETTER_QUEUE_ENABLED)); + } + + private long getBrokerAttributeAsLong(String name) + { + Number brokerValue = (Number)_broker.getAttribute(name); + return brokerValue == null? 0 : brokerValue.longValue(); + } + + private int getBrokerAttributeAsInt(String name) + { + Number brokerValue = (Number)_broker.getAttribute(name); + return brokerValue == null? 0 : brokerValue.intValue(); + } + + private boolean getBrokerAttributeAsBoolean(String name) + { + Boolean brokerValue = (Boolean)_broker.getAttribute(name); + return brokerValue == null? false : brokerValue.booleanValue(); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/XmlConfigurationUtilities.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/XmlConfigurationUtilities.java new file mode 100644 index 0000000000..c0cff2c109 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/XmlConfigurationUtilities.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.configuration; + +import java.io.File; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.commons.configuration.CompositeConfiguration; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.ConfigurationFactory; +import org.apache.commons.configuration.SystemConfiguration; +import org.apache.commons.configuration.XMLConfiguration; + +public class XmlConfigurationUtilities +{ + + // Our configuration class needs to make the interpolate method + // public so it can be called below from the config method. + public static class MyConfiguration extends CompositeConfiguration + { + public String interpolate(String obj) + { + return super.interpolate(obj); + } + } + + public static Configuration parseConfig(File file, Map envVarMap) throws ConfigurationException + { + ConfigurationFactory factory = new ConfigurationFactory(); + factory.setConfigurationFileName(file.getAbsolutePath()); + Configuration conf = factory.getConfiguration(); + + Iterator keys = conf.getKeys(); + if (!keys.hasNext()) + { + keys = null; + conf = flatConfig(file); + } + + XmlConfigurationUtilities.substituteEnvironmentVariables(conf, envVarMap); + return conf; + } + + public final static Configuration flatConfig(File file) throws ConfigurationException + { + // We have to override the interpolate methods so that + // interpolation takes place across the entirety of the + // composite configuration. Without doing this each + // configuration object only interpolates variables defined + // inside itself. + final MyConfiguration conf = new MyConfiguration(); + conf.addConfiguration(new SystemConfiguration() + { + protected String interpolate(String o) + { + return conf.interpolate(o); + } + }); + conf.addConfiguration(new XMLConfiguration(file) + { + protected String interpolate(String o) + { + return conf.interpolate(o); + } + }); + return conf; + } + + static void substituteEnvironmentVariables(Configuration conf, Map envVarMap) + { + if (envVarMap == null || envVarMap.isEmpty()) + { + return; + } + for (Entry var : envVarMap.entrySet()) + { + String val = System.getenv(var.getKey()); + if (val != null) + { + conf.setProperty(var.getValue(), val); + } + } + } + + + public static String escapeTagName(String name) + { + return name.replaceAll("\\.", "\\.\\."); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/AbstractConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/AbstractConfiguration.java new file mode 100644 index 0000000000..3c17faef75 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/AbstractConfiguration.java @@ -0,0 +1,329 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.configuration.plugins; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.ConversionException; +import org.apache.log4j.Logger; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; + +public abstract class AbstractConfiguration +{ + protected static final Logger _logger = Logger.getLogger(AbstractConfiguration.class); + + private Configuration _config; + + /** + * The Elements that this Plugin can process. + * + * For a Queues plugin that would be a list containing: + *

    + *
  • queue - the queue entries + *
  • the alerting values for defaults + *
  • exchange - the default exchange + *
  • durable - set the default durablity + *
+ */ + abstract public String[] getElementsProcessed(); + + /** Performs configuration validation. */ + public void validateConfiguration() throws ConfigurationException + { + // Override in sub-classes + } + + public Configuration getConfig() + { + return _config; + } + + /** + * Sets the configuration for this plugin + * + * @param path + * @param configuration the configuration for this plugin. + */ + public void setConfiguration(String path, Configuration configuration) throws ConfigurationException + { + _config = configuration; + + // Extract a list of elements for processing + Iterator keys = configuration.getKeys(); + + Set elements = new HashSet(); + while (keys.hasNext()) + { + String key = (String) keys.next(); + + int elementNameIndex = key.indexOf("."); + + String element = key.trim(); + if (elementNameIndex != -1) + { + element = key.substring(0, elementNameIndex).trim(); + } + + // Trim any element properties + elementNameIndex = element.indexOf("["); + if (elementNameIndex > 0) + { + element = element.substring(0, elementNameIndex).trim(); + } + + elements.add(element); + } + + //Remove the items we already expect in the configuration + for (String tag : getElementsProcessed()) + { + + // Work round the issue with Commons configuration. + // With an XMLConfiguration the key will be [@property] + // but with a CompositeConfiguration it will be @property]. + // Hide this issue from our users so when/if we change the + // configuration they don't have to. + int bracketIndex = tag.indexOf("["); + if (bracketIndex != -1) + { + tag = tag.substring(bracketIndex + 1, tag.length()); + } + + elements.remove(tag); + } + + if (_logger.isInfoEnabled()) + { + if (!elements.isEmpty()) + { + _logger.info("Elements to lookup:" + path); + for (String tag : elements) + { + _logger.info("Tag:'" + tag + "'"); + } + } + } + + validateConfiguration(); + } + + /** Helper method to print out list of keys in a {@link Configuration}. */ + public static final void showKeys(Configuration config) + { + if (config.isEmpty()) + { + _logger.info("Configuration is empty"); + } + else + { + Iterator keys = config.getKeys(); + while (keys.hasNext()) + { + String key = (String) keys.next(); + _logger.info("Configuration key: " + key); + } + } + } + + protected boolean hasConfiguration() + { + return _config != null; + } + + /// Getters + + protected double getDoubleValue(String property) + { + return getDoubleValue(property, 0.0); + } + + protected double getDoubleValue(String property, double defaultValue) + { + return _config.getDouble(property, defaultValue); + } + + protected long getLongValue(String property) + { + return getLongValue(property, 0); + } + + protected long getLongValue(String property, long defaultValue) + { + return _config.getLong(property, defaultValue); + } + + protected int getIntValue(String property) + { + return getIntValue(property, 0); + } + + protected int getIntValue(String property, int defaultValue) + { + return _config.getInt(property, defaultValue); + } + + protected String getStringValue(String property) + { + return getStringValue(property, null); + } + + protected String getStringValue(String property, String defaultValue) + { + return _config.getString(property, defaultValue); + } + + protected boolean getBooleanValue(String property) + { + return getBooleanValue(property, false); + } + + protected boolean getBooleanValue(String property, boolean defaultValue) + { + return _config.getBoolean(property, defaultValue); + } + + protected List getListValue(String property) + { + return getListValue(property, Collections.EMPTY_LIST); + } + + protected List getListValue(String property, List defaultValue) + { + return _config.getList(property, defaultValue); + } + + /// Validation Helpers + + protected boolean contains(String property) + { + return _config.getProperty(property) != null; + } + + /** + * Provide mechanism to validate Configuration contains a Postiive Long Value + * + * @param property + * + * @throws ConfigurationException + */ + protected void validatePositiveLong(String property) throws ConfigurationException + { + try + { + if (!containsPositiveLong(property)) + { + throw new ConfigurationException(this.getClass().getSimpleName() + + ": '" + property + + "' must be a Positive Long value."); + } + } + catch (Exception e) + { + Throwable last = e; + + // Find the first cause + if (e instanceof ConversionException) + { + Throwable t = e.getCause(); + while (t != null) + { + last = t; + t = last.getCause(); + } + } + + throw new ConfigurationException(this.getClass().getSimpleName() + + ": unable to configure invalid " + + property + ":" + + _config.getString(property), + last); + } + } + + protected boolean containsLong(String property) + { + try + { + _config.getLong(property); + return true; + } + catch (NoSuchElementException e) + { + return false; + } + } + + protected boolean containsPositiveLong(String property) + { + try + { + long value = _config.getLong(property); + return value > 0; + } + catch (NoSuchElementException e) + { + return false; + } + + } + + protected boolean containsInt(String property) + { + try + { + _config.getInt(property); + return true; + } + catch (NoSuchElementException e) + { + return false; + } + } + + protected boolean containsBoolean(String property) + { + try + { + _config.getBoolean(property); + return true; + } + catch (NoSuchElementException e) + { + return false; + } + } + + public static String escapeTagName(String name) + { + return name.replaceAll("\\.", "\\.\\."); + } + + protected void setConfig(Configuration config) + { + _config = config; + } +} + + diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java deleted file mode 100644 index d08e3bc806..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java +++ /dev/null @@ -1,488 +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.configuration.plugins; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.ConversionException; -import org.apache.log4j.Logger; - -import org.apache.qpid.server.configuration.ConfigurationManager; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; - -public abstract class ConfigurationPlugin -{ - protected static final Logger _logger = Logger.getLogger(ConfigurationPlugin.class); - - private Map - _pluginConfiguration = new HashMap(); - - private Configuration _config; - - /** - * The Elements that this Plugin can process. - * - * For a Queues plugin that would be a list containing: - *
    - *
  • queue - the queue entries - *
  • the alerting values for defaults - *
  • exchange - the default exchange - *
  • durable - set the default durablity - *
- */ - abstract public String[] getElementsProcessed(); - - /** Performs configuration validation. */ - public void validateConfiguration() throws ConfigurationException - { - // Override in sub-classes - } - - public Configuration getConfig() - { - return _config; - } - - public C getConfiguration(String plugin) - { - return (C) _pluginConfiguration.get(plugin); - } - - /** - * Sets the configuration for this plugin - * - * @param path - * @param configuration the configuration for this plugin. - */ - public void setConfiguration(String path, Configuration configuration) throws ConfigurationException - { - _config = configuration; - - // Extract a list of elements for processing - Iterator keys = configuration.getKeys(); - - Set elements = new HashSet(); - while (keys.hasNext()) - { - String key = (String) keys.next(); - - int elementNameIndex = key.indexOf("."); - - String element = key.trim(); - if (elementNameIndex != -1) - { - element = key.substring(0, elementNameIndex).trim(); - } - - // Trim any element properties - elementNameIndex = element.indexOf("["); - if (elementNameIndex > 0) - { - element = element.substring(0, elementNameIndex).trim(); - } - - elements.add(element); - } - - //Remove the items we already expect in the configuration - for (String tag : getElementsProcessed()) - { - - // Work round the issue with Commons configuration. - // With an XMLConfiguration the key will be [@property] - // but with a CompositeConfiguration it will be @property]. - // Hide this issue from our users so when/if we change the - // configuration they don't have to. - int bracketIndex = tag.indexOf("["); - if (bracketIndex != -1) - { - tag = tag.substring(bracketIndex + 1, tag.length()); - } - - elements.remove(tag); - } - - if (_logger.isInfoEnabled()) - { - if (!elements.isEmpty()) - { - _logger.info("Elements to lookup:" + path); - for (String tag : elements) - { - _logger.info("Tag:'" + tag + "'"); - } - } - } - - offerRemainingConfigurationToOtherPlugins(path, configuration, elements); - - validateConfiguration(); - } - - private void offerRemainingConfigurationToOtherPlugins(String path, - Configuration configuration, Set elements) throws ConfigurationException - { - final IApplicationRegistry appRegistry = safeGetApplicationRegistryInstance(); - - if (appRegistry == null) - { - // We see this happen during shutdown due to asynchronous reconfig using IO threads. - // Need to remove the responsibility for offering configuration to other class. - _logger.info("Cannot offer remaining config to other plugins, can't find app registry"); - return; - } - - final ConfigurationManager configurationManager = appRegistry.getConfigurationManager(); - // Process the elements in the configuration - for (String element : elements) - { - Configuration handled = element.length() == 0 ? configuration : configuration.subset(element); - - String configurationElement = element; - if (path.length() > 0) - { - configurationElement = path + "." + configurationElement; - } - - List handlers = configurationManager.getConfigurationPlugins(configurationElement, handled); - - if(_logger.isDebugEnabled()) - { - _logger.debug("For '" + element + "' found handlers (" + handlers.size() + "):" + handlers); - } - - for (ConfigurationPlugin plugin : handlers) - { - _pluginConfiguration.put(plugin.getClass().getName(), plugin); - } - } - } - - private IApplicationRegistry safeGetApplicationRegistryInstance() - { - try - { - return ApplicationRegistry.getInstance(); - } - catch (IllegalStateException ise) - { - return null; - } - } - - /** Helper method to print out list of keys in a {@link Configuration}. */ - public static final void showKeys(Configuration config) - { - if (config.isEmpty()) - { - _logger.info("Configuration is empty"); - } - else - { - Iterator keys = config.getKeys(); - while (keys.hasNext()) - { - String key = (String) keys.next(); - _logger.info("Configuration key: " + key); - } - } - } - - protected boolean hasConfiguration() - { - return _config != null; - } - - /// Getters - - protected double getDoubleValue(String property) - { - return getDoubleValue(property, 0.0); - } - - protected double getDoubleValue(String property, double defaultValue) - { - return _config.getDouble(property, defaultValue); - } - - protected long getLongValue(String property) - { - return getLongValue(property, 0); - } - - protected long getLongValue(String property, long defaultValue) - { - return _config.getLong(property, defaultValue); - } - - protected int getIntValue(String property) - { - return getIntValue(property, 0); - } - - protected int getIntValue(String property, int defaultValue) - { - return _config.getInt(property, defaultValue); - } - - protected String getStringValue(String property) - { - return getStringValue(property, null); - } - - protected String getStringValue(String property, String defaultValue) - { - return _config.getString(property, defaultValue); - } - - protected boolean getBooleanValue(String property) - { - return getBooleanValue(property, false); - } - - protected boolean getBooleanValue(String property, boolean defaultValue) - { - return _config.getBoolean(property, defaultValue); - } - - protected List getListValue(String property) - { - return getListValue(property, Collections.EMPTY_LIST); - } - - protected List getListValue(String property, List defaultValue) - { - return _config.getList(property, defaultValue); - } - - /// Validation Helpers - - protected boolean contains(String property) - { - return _config.getProperty(property) != null; - } - - /** - * Provide mechanism to validate Configuration contains a Postiive Long Value - * - * @param property - * - * @throws ConfigurationException - */ - protected void validatePositiveLong(String property) throws ConfigurationException - { - try - { - if (!containsPositiveLong(property)) - { - throw new ConfigurationException(this.getClass().getSimpleName() - + ": '" + property + - "' must be a Positive Long value."); - } - } - catch (Exception e) - { - Throwable last = e; - - // Find the first cause - if (e instanceof ConversionException) - { - Throwable t = e.getCause(); - while (t != null) - { - last = t; - t = last.getCause(); - } - } - - throw new ConfigurationException(this.getClass().getSimpleName() + - ": unable to configure invalid " + - property + ":" + - _config.getString(property), - last); - } - } - - protected boolean containsLong(String property) - { - try - { - _config.getLong(property); - return true; - } - catch (NoSuchElementException e) - { - return false; - } - } - - protected boolean containsPositiveLong(String property) - { - try - { - long value = _config.getLong(property); - return value > 0; - } - catch (NoSuchElementException e) - { - return false; - } - - } - - protected boolean containsInt(String property) - { - try - { - _config.getInt(property); - return true; - } - catch (NoSuchElementException e) - { - return false; - } - } - - protected boolean containsBoolean(String property) - { - try - { - _config.getBoolean(property); - return true; - } - catch (NoSuchElementException e) - { - return false; - } - } - - /** - * Given another configuration merge the configuration into our own config - * - * The new values being merged in will take precedence over existing values. - * - * In the simplistic case this means something like: - * - * So if we have configuration set - * name = 'fooo' - * - * And the new configuration contains a name then that will be reset. - * name = 'new' - * - * However this plugin will simply contain other plugins so the merge will - * be called until we end up at a base plugin that understand how to merge - * items. i.e Alerting values. Where the provided configuration will take - * precedence. - * - * @param configuration the config to merge in to our own. - */ - public void addConfiguration(ConfigurationPlugin configuration) - { - // If given configuration is null then there is nothing to process. - if (configuration == null) - { - return; - } - - // Merge all the sub configuration items - for (Map.Entry newPlugins : configuration._pluginConfiguration.entrySet()) - { - String key = newPlugins.getKey(); - ConfigurationPlugin config = newPlugins.getValue(); - - if (_pluginConfiguration.containsKey(key)) - { - //Merge the configuration if we already have this type of config - _pluginConfiguration.get(key).mergeConfiguration(config); - } - else - { - //otherwise just add it to our config. - _pluginConfiguration.put(key, config); - } - } - - //Merge the configuration itself - String key = configuration.getClass().getName(); - if (_pluginConfiguration.containsKey(key)) - { - //Merge the configuration if we already have this type of config - _pluginConfiguration.get(key).mergeConfiguration(configuration); - } - else - { - //If we are adding a configuration of our own type then merge - if (configuration.getClass() == this.getClass()) - { - mergeConfiguration(configuration); - } - else - { - // just store this in case someone else needs it. - _pluginConfiguration.put(key, configuration); - } - - } - - } - - protected void mergeConfiguration(ConfigurationPlugin configuration) - { - _config = configuration.getConfig(); - } - - public String toString() - { - StringBuilder sb = new StringBuilder(); - - sb.append("\n").append(getClass().getSimpleName()); - sb.append("=[ (").append(formatToString()).append(")"); - - for(Map.Entry item : _pluginConfiguration.entrySet()) - { - sb.append("\n").append(item.getValue()); - } - - sb.append("]\n"); - - return sb.toString(); - } - - public String formatToString() - { - return super.toString(); - } - - protected void setConfig(Configuration config) - { - _config = config; - } -} - - diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPluginFactory.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPluginFactory.java deleted file mode 100644 index fa41f3ef06..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPluginFactory.java +++ /dev/null @@ -1,38 +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.configuration.plugins; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import java.util.List; - -public interface ConfigurationPluginFactory -{ - /** - * The Parent paths of the configuration that this plugin supports. - * - * For example, {@code queue} elements have a parent path of {@code virtualhosts.virtualhost}. - */ - public List getParentPaths(); - - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException; -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionConfiguration.java deleted file mode 100644 index a90b1d514f..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionConfiguration.java +++ /dev/null @@ -1,86 +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.configuration.plugins; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.TimeUnit; - -public class SlowConsumerDetectionConfiguration extends ConfigurationPlugin -{ - public static class SlowConsumerDetectionConfigurationFactory implements ConfigurationPluginFactory - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - SlowConsumerDetectionConfiguration slowConsumerConfig = new SlowConsumerDetectionConfiguration(); - slowConsumerConfig.setConfiguration(path, config); - return slowConsumerConfig; - } - - public List getParentPaths() - { - return Arrays.asList("virtualhosts.virtualhost.slow-consumer-detection"); - } - } - - //Set Default time unit to seconds - private TimeUnit _timeUnit = TimeUnit.SECONDS; - - public String[] getElementsProcessed() - { - return new String[]{"delay", - "timeunit"}; - } - - public long getDelay() - { - return getLongValue("delay", 10); - } - - public TimeUnit getTimeUnit() - { - return _timeUnit; - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - validatePositiveLong("delay"); - - String timeUnit = getStringValue("timeunit"); - - if (timeUnit != null) - { - try - { - _timeUnit = TimeUnit.valueOf(timeUnit.toUpperCase()); - } - catch (IllegalArgumentException iae) - { - throw new ConfigurationException("Unable to configure Slow Consumer Detection invalid TimeUnit:" + timeUnit); - } - } - - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionPolicyConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionPolicyConfiguration.java deleted file mode 100644 index a9026c6164..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionPolicyConfiguration.java +++ /dev/null @@ -1,74 +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.configuration.plugins; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import java.util.Arrays; -import java.util.List; - -public class SlowConsumerDetectionPolicyConfiguration extends ConfigurationPlugin -{ - public static class SlowConsumerDetectionPolicyConfigurationFactory implements ConfigurationPluginFactory - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - SlowConsumerDetectionPolicyConfiguration slowConsumerConfig = new SlowConsumerDetectionPolicyConfiguration(); - slowConsumerConfig.setConfiguration(path, config); - return slowConsumerConfig; - } - - public List getParentPaths() - { - return Arrays.asList( - "virtualhosts.virtualhost.queues.slow-consumer-detection.policy", - "virtualhosts.virtualhost.queues.queue.slow-consumer-detection.policy", - "virtualhosts.virtualhost.topics.slow-consumer-detection.policy", - "virtualhosts.virtualhost.topics.topic.slow-consumer-detection.policy"); - } - } - - public String[] getElementsProcessed() - { - return new String[]{"name"}; - } - - public String getPolicyName() - { - return getStringValue("name"); - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - if (getPolicyName() == null) - { - throw new ConfigurationException("No Slow consumer policy defined."); - } - } - - @Override - public String formatToString() - { - return "Policy:"+getPolicyName(); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionQueueConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionQueueConfiguration.java deleted file mode 100644 index cb3bb5a77f..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/SlowConsumerDetectionQueueConfiguration.java +++ /dev/null @@ -1,163 +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.configuration.plugins; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.plugins.PluginManager; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPlugin; -import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPluginFactory; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -public class SlowConsumerDetectionQueueConfiguration extends ConfigurationPlugin -{ - private SlowConsumerPolicyPlugin _policyPlugin; - - public static class SlowConsumerDetectionQueueConfigurationFactory implements ConfigurationPluginFactory - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - SlowConsumerDetectionQueueConfiguration slowConsumerConfig = new SlowConsumerDetectionQueueConfiguration(); - slowConsumerConfig.setConfiguration(path, config); - return slowConsumerConfig; - } - - public List getParentPaths() - { - return Arrays.asList( - "virtualhosts.virtualhost.queues.slow-consumer-detection", - "virtualhosts.virtualhost.queues.queue.slow-consumer-detection", - "virtualhosts.virtualhost.topics.slow-consumer-detection", - "virtualhosts.virtualhost.topics.topic.slow-consumer-detection"); - } - } - - public String[] getElementsProcessed() - { - return new String[]{"messageAge", - "depth", - "messageCount"}; - } - - public long getMessageAge() - { - return getLongValue("messageAge"); - } - - public long getDepth() - { - return getLongValue("depth"); - } - - public long getMessageCount() - { - return getLongValue("messageCount"); - } - - public SlowConsumerPolicyPlugin getPolicy() - { - return _policyPlugin; - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - PluginManager pluginManager; - try - { - pluginManager = ApplicationRegistry.getInstance().getPluginManager(); - } - catch (IllegalStateException ise) - { - // We see this happen during shutdown due to asynchronous reconfig performed IO threads - // running at the same time as the shutdown handler. - _policyPlugin = null; - return; - } - - if (!containsPositiveLong("messageAge") && - !containsPositiveLong("depth") && - !containsPositiveLong("messageCount")) - { - throw new ConfigurationException("At least one configuration property" + - "('messageAge','depth' or 'messageCount') must be specified."); - } - - SlowConsumerDetectionPolicyConfiguration policyConfig = getConfiguration(SlowConsumerDetectionPolicyConfiguration.class.getName()); - Map factories = pluginManager.getSlowConsumerPlugins(); - - if (policyConfig == null) - { - throw new ConfigurationException("No Slow Consumer Policy specified. Known Policies:" + factories.keySet()); - } - - if (_logger.isDebugEnabled()) - { - Iterator keys = policyConfig.getConfig().getKeys(); - - while (keys.hasNext()) - { - String key = (String) keys.next(); - - _logger.debug("Policy Keys:" + key); - } - - } - - SlowConsumerPolicyPluginFactory pluginFactory = factories.get(policyConfig.getPolicyName().toLowerCase()); - - if (pluginFactory == null) - { - throw new ConfigurationException("Unknown Slow Consumer Policy specified:" + policyConfig.getPolicyName() + " Known Policies:" + factories.keySet()); - } - - _policyPlugin = pluginFactory.newInstance(policyConfig); - - // Debug the creation of this Config - _logger.debug(this); - } - - public String formatToString() - { - StringBuilder sb = new StringBuilder(); - if (getMessageAge() > 0) - { - sb.append("Age:").append(getMessageAge()).append(":"); - } - if (getDepth() > 0) - { - sb.append("Depth:").append(getDepth()).append(":"); - } - if (getMessageCount() > 0) - { - sb.append("Count:").append(getMessageCount()).append(":"); - } - - sb.append("Policy[").append(getPolicy()).append("]"); - return sb.toString(); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java new file mode 100644 index 0000000000..9b06a2b499 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java @@ -0,0 +1,55 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import java.util.Map; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; + +public class AuthenticationProviderRecoverer implements ConfiguredObjectRecoverer +{ + private final AuthenticationProviderFactory _authenticationProviderFactory; + + public AuthenticationProviderRecoverer(AuthenticationProviderFactory authenticationProviderFactory) + { + _authenticationProviderFactory = authenticationProviderFactory; + } + + @Override + public AuthenticationProvider create(RecovererProvider recovererProvider, ConfigurationEntry configurationEntry, ConfiguredObject... parents) + { + Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents); + Map attributes = configurationEntry.getAttributes(); + AuthenticationProvider authenticationProvider = _authenticationProviderFactory.create( + configurationEntry.getId(), + broker, + attributes, null); + + return authenticationProvider; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java new file mode 100644 index 0000000000..4bfa0ca7a3 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java @@ -0,0 +1,139 @@ +package org.apache.qpid.server.configuration.startup; + +import java.util.Collection; +import java.util.Map; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; +import org.apache.qpid.server.model.adapter.BrokerAdapter; +import org.apache.qpid.server.model.adapter.PortFactory; +import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.security.group.GroupPrincipalAccessor; +import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; + +public class BrokerRecoverer implements ConfiguredObjectRecoverer +{ + private final StatisticsGatherer _statisticsGatherer; + private final VirtualHostRegistry _virtualHostRegistry; + private final LogRecorder _logRecorder; + private final RootMessageLogger _rootMessageLogger; + private final AuthenticationProviderFactory _authenticationProviderFactory; + private final PortFactory _portFactory; + private final TaskExecutor _taskExecutor; + + public BrokerRecoverer(AuthenticationProviderFactory authenticationProviderFactory, PortFactory portFactory, + StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, + RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor) + { + _portFactory = portFactory; + _authenticationProviderFactory = authenticationProviderFactory; + _statisticsGatherer = statisticsGatherer; + _virtualHostRegistry = virtualHostRegistry; + _logRecorder = logRecorder; + _rootMessageLogger = rootMessageLogger; + _taskExecutor = taskExecutor; + } + + @Override + public Broker create(RecovererProvider recovererProvider, ConfigurationEntry entry, ConfiguredObject... parents) + { + StoreConfigurationChangeListener storeChangeListener = new StoreConfigurationChangeListener(entry.getStore()); + BrokerAdapter broker = new BrokerAdapter(entry.getId(), entry.getAttributes(), _statisticsGatherer, _virtualHostRegistry, + _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _portFactory, _taskExecutor); + broker.addChangeListener(storeChangeListener); + Map> childEntries = entry.getChildren(); + for (String type : childEntries.keySet()) + { + ConfiguredObjectRecoverer recoverer = recovererProvider.getRecoverer(type); + if (recoverer == null) + { + throw new IllegalConfigurationException("Cannot recover entry for the type '" + type + "' from broker"); + } + Collection entries = childEntries.get(type); + for (ConfigurationEntry childEntry : entries) + { + ConfiguredObject object = recoverer.create(recovererProvider, childEntry, broker); + if (object == null) + { + throw new IllegalConfigurationException("Cannot create configured object for the entry " + childEntry); + } + broker.recoverChild(object); + object.addChangeListener(storeChangeListener); + } + } + wireUpConfiguredObjects(broker, entry.getAttributes()); + + return broker; + } + + private void wireUpConfiguredObjects(BrokerAdapter broker, Map brokerAttributes) + { + AuthenticationProvider defaultAuthenticationProvider = null; + Collection authenticationProviders = broker.getAuthenticationProviders(); + int numberOfAuthenticationProviders = authenticationProviders.size(); + if (numberOfAuthenticationProviders == 0) + { + throw new IllegalConfigurationException("No authentication provider was configured"); + } + else if (numberOfAuthenticationProviders == 1) + { + defaultAuthenticationProvider = authenticationProviders.iterator().next(); + } + else + { + String name = (String) brokerAttributes.get(Broker.DEFAULT_AUTHENTICATION_PROVIDER); + if (name == null) + { + throw new IllegalConfigurationException("Multiple authentication providers defined, but no default was configured."); + } + + defaultAuthenticationProvider = getAuthenticationProviderByName(broker, name); + } + broker.setDefaultAuthenticationProvider(defaultAuthenticationProvider); + + GroupPrincipalAccessor groupPrincipalAccessor = new GroupPrincipalAccessor(broker.getGroupProviders()); + for (AuthenticationProvider authenticationProvider : authenticationProviders) + { + authenticationProvider.setGroupAccessor(groupPrincipalAccessor); + } + + Collection ports = broker.getPorts(); + for (Port port : ports) + { + String authenticationProviderName = (String) port.getAttribute(Port.AUTHENTICATION_MANAGER); + AuthenticationProvider provider = null; + if (authenticationProviderName != null) + { + provider = getAuthenticationProviderByName(broker, authenticationProviderName); + } + else + { + provider = defaultAuthenticationProvider; + } + port.setAuthenticationProvider(provider); + } + } + + private AuthenticationProvider getAuthenticationProviderByName(BrokerAdapter broker, String authenticationProviderName) + { + AuthenticationProvider provider = broker.getAuthenticationProviderByName(authenticationProviderName); + if (provider == null) + { + throw new IllegalConfigurationException("Cannot find the authentication provider with name: " + + authenticationProviderName); + } + return provider; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java new file mode 100644 index 0000000000..15cb229d8a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java @@ -0,0 +1,112 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.KeyStore; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; +import org.apache.qpid.server.model.adapter.PortFactory; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.plugin.GroupManagerFactory; +import org.apache.qpid.server.plugin.PluginFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; +import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; + +public class DefaultRecovererProvider implements RecovererProvider +{ + + private final StatisticsGatherer _brokerStatisticsGatherer; + private final VirtualHostRegistry _virtualHostRegistry; + private final LogRecorder _logRecorder; + private final RootMessageLogger _rootMessageLogger; + private final AuthenticationProviderFactory _authenticationProviderFactory; + private final PortFactory _portFactory; + private final QpidServiceLoader _groupManagerServiceLoader; + private final QpidServiceLoader _pluginFactoryServiceLoader; + private final TaskExecutor _taskExecutor; + + public DefaultRecovererProvider(StatisticsGatherer brokerStatisticsGatherer, VirtualHostRegistry virtualHostRegistry, + LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor) + { + _authenticationProviderFactory = new AuthenticationProviderFactory(new QpidServiceLoader()); + _portFactory = new PortFactory(); + _brokerStatisticsGatherer = brokerStatisticsGatherer; + _virtualHostRegistry = virtualHostRegistry; + _logRecorder = logRecorder; + _rootMessageLogger = rootMessageLogger; + _groupManagerServiceLoader = new QpidServiceLoader(); + _pluginFactoryServiceLoader = new QpidServiceLoader(); + _taskExecutor = taskExecutor; + } + + @Override + public ConfiguredObjectRecoverer getRecoverer(String type) + { + if (Broker.class.getSimpleName().equals(type)) + { + return new BrokerRecoverer(_authenticationProviderFactory, _portFactory, _brokerStatisticsGatherer, _virtualHostRegistry, + _logRecorder, _rootMessageLogger, _taskExecutor); + } + else if(VirtualHost.class.getSimpleName().equals(type)) + { + return new VirtualHostRecoverer(_brokerStatisticsGatherer); + } + else if(AuthenticationProvider.class.getSimpleName().equals(type)) + { + return new AuthenticationProviderRecoverer(_authenticationProviderFactory); + } + else if(Port.class.getSimpleName().equals(type)) + { + return new PortRecoverer(_portFactory); + } + else if(GroupProvider.class.getSimpleName().equals(type)) + { + return new GroupProviderRecoverer(_groupManagerServiceLoader); + } + else if(KeyStore.class.getSimpleName().equals(type)) + { + return new KeyStoreRecoverer(); + } + else if(TrustStore.class.getSimpleName().equals(type)) + { + return new TrustStoreRecoverer(); + } + else if(Plugin.class.getSimpleName().equals(type)) + { + return new PluginRecoverer(_pluginFactoryServiceLoader); + } + + return null; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java new file mode 100644 index 0000000000..275a0c736c --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/GroupProviderRecoverer.java @@ -0,0 +1,74 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import java.util.Map; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.adapter.GroupProviderAdapter; +import org.apache.qpid.server.plugin.GroupManagerFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; +import org.apache.qpid.server.security.group.GroupManager; + +public class GroupProviderRecoverer implements ConfiguredObjectRecoverer +{ + private QpidServiceLoader _groupManagerServiceLoader; + + public GroupProviderRecoverer(QpidServiceLoader groupManagerServiceLoader) + { + super(); + _groupManagerServiceLoader = groupManagerServiceLoader; + } + + @Override + public GroupProvider create(RecovererProvider recovererProvider, ConfigurationEntry configurationEntry, ConfiguredObject... parents) + { + Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents); + Map attributes = configurationEntry.getAttributes(); + GroupManager groupManager = createGroupManager(attributes); + if (groupManager == null) + { + throw new IllegalConfigurationException("Cannot create GroupManager from attributes : " + attributes); + } + GroupProviderAdapter groupProviderAdapter = new GroupProviderAdapter(configurationEntry.getId(), groupManager, broker); + return groupProviderAdapter; + } + + private GroupManager createGroupManager(Map attributes) + { + for(GroupManagerFactory factory : _groupManagerServiceLoader.instancesOf(GroupManagerFactory.class)) + { + GroupManager groupManager = factory.createInstance(attributes); + if (groupManager != null) + { + return groupManager; + } + } + return null; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/KeyStoreRecoverer.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/KeyStoreRecoverer.java new file mode 100644 index 0000000000..8efedd37b5 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/KeyStoreRecoverer.java @@ -0,0 +1,40 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.KeyStore; +import org.apache.qpid.server.model.adapter.KeyStoreAdapter; + +public class KeyStoreRecoverer implements ConfiguredObjectRecoverer +{ + @Override + public KeyStore create(RecovererProvider recovererProvider, ConfigurationEntry entry, ConfiguredObject... parents) + { + Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents); + return new KeyStoreAdapter(entry.getId(), broker, entry.getAttributes()); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PluginRecoverer.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PluginRecoverer.java new file mode 100644 index 0000000000..ddc4482953 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PluginRecoverer.java @@ -0,0 +1,66 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.plugin.PluginFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +public class PluginRecoverer implements ConfiguredObjectRecoverer +{ + private QpidServiceLoader _serviceLoader; + + public PluginRecoverer(QpidServiceLoader serviceLoader) + { + _serviceLoader = serviceLoader; + } + + @Override + public ConfiguredObject create(RecovererProvider recovererProvider, ConfigurationEntry configurationEntry, ConfiguredObject... parents) + { + Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents); + Map attributes = configurationEntry.getAttributes(); + Iterable factories = _serviceLoader.instancesOf(PluginFactory.class); + for (PluginFactory pluginFactory : factories) + { + UUID configurationId = configurationEntry.getId(); + ConfiguredObject pluginObject = pluginFactory.createInstance(configurationId, attributes, broker); + if (pluginObject != null) + { + UUID pluginId = pluginObject.getId(); + if (!configurationId.equals(pluginId)) + { + throw new IllegalStateException("Plugin object id '" + pluginId + "' does not equal expected id " + configurationId); + } + return pluginObject; + } + } + throw new IllegalConfigurationException("Cannot create a plugin object for " + attributes + " with factories " + factories); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PortRecoverer.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PortRecoverer.java new file mode 100644 index 0000000000..147e835a8d --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PortRecoverer.java @@ -0,0 +1,52 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.adapter.BrokerAdapter; +import org.apache.qpid.server.model.adapter.PortFactory; + +public class PortRecoverer implements ConfiguredObjectRecoverer +{ + /** + * delegates to a {@link PortFactory} so that the logic can be shared by + * {@link BrokerAdapter} + */ + private final PortFactory _portFactory; + + public PortRecoverer(PortFactory portFactory) + { + _portFactory = portFactory; + } + + @Override + public Port create(RecovererProvider recovererProvider, ConfigurationEntry configurationEntry, ConfiguredObject... parents) + { + Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents); + return _portFactory.createPort(configurationEntry.getId(), broker, configurationEntry.getAttributes()); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/RecovererHelper.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/RecovererHelper.java new file mode 100644 index 0000000000..b60c9c289f --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/RecovererHelper.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; + +public class RecovererHelper +{ + public static Broker verifyOnlyBrokerIsParent(ConfiguredObject... parents) + { + if (parents == null || parents.length == 0) + { + throw new IllegalArgumentException("Broker parent is not passed!"); + } + if (parents.length != 1) + { + throw new IllegalArgumentException("Only one parent is expected!"); + } + if (!(parents[0] instanceof Broker)) + { + throw new IllegalArgumentException("Parent is not a broker"); + } + return (Broker)parents[0]; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/TrustStoreRecoverer.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/TrustStoreRecoverer.java new file mode 100644 index 0000000000..7e9428a4d6 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/TrustStoreRecoverer.java @@ -0,0 +1,40 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.adapter.TrustStoreAdapter; + +public class TrustStoreRecoverer implements ConfiguredObjectRecoverer +{ + @Override + public TrustStore create(RecovererProvider recovererProvider, ConfigurationEntry entry, ConfiguredObject... parents) + { + Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents); + return new TrustStoreAdapter(entry.getId(), broker, entry.getAttributes()); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/VirtualHostRecoverer.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/VirtualHostRecoverer.java new file mode 100644 index 0000000000..4f863adfb5 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/VirtualHostRecoverer.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.adapter.VirtualHostAdapter; +import org.apache.qpid.server.stats.StatisticsGatherer; + +public class VirtualHostRecoverer implements ConfiguredObjectRecoverer +{ + private StatisticsGatherer _brokerStatisticsGatherer; + + public VirtualHostRecoverer(StatisticsGatherer brokerStatisticsGatherer) + { + super(); + _brokerStatisticsGatherer = brokerStatisticsGatherer; + } + + @Override + public VirtualHost create(RecovererProvider recovererProvider, ConfigurationEntry entry, ConfiguredObject... parents) + { + Broker broker = RecovererHelper.verifyOnlyBrokerIsParent(parents); + + return new VirtualHostAdapter(entry.getId(), entry.getAttributes(), broker, _brokerStatisticsGatherer, broker.getTaskExecutor()); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStore.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStore.java new file mode 100644 index 0000000000..e11b63001a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStore.java @@ -0,0 +1,711 @@ +package org.apache.qpid.server.configuration.store; + +import static org.apache.qpid.server.configuration.ConfigurationEntry.ATTRIBUTE_NAME; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.util.FileUtils; +import org.apache.qpid.util.Strings; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.node.ArrayNode; + +public class JsonConfigurationEntryStore implements ConfigurationEntryStore +{ + public static final String STORE_TYPE = "json"; + public static final String IN_MEMORY = ":memory:"; + + private static final String DEFAULT_BROKER_NAME = "Broker"; + private static final String ID = "id"; + private static final String TYPE = "@type"; + + private ObjectMapper _objectMapper; + private Map _entries; + private File _storeFile; + private UUID _rootId; + private Map> _relationshipClasses; + + public JsonConfigurationEntryStore() + { + _objectMapper = new ObjectMapper(); + _objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + _objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); + _entries = new HashMap(); + _relationshipClasses = buildRelationshipClassMap(); + } + + @Override + public void open(String storeLocation) + { + if (_rootId != null) + { + throw new IllegalConfigurationException("The store has been opened alread"); + } + if (!IN_MEMORY.equals(storeLocation)) + { + _storeFile = new File(storeLocation); + } + createOrLoadStore(); + } + + @Override + public void open(String storeLocation, String initialStoreLocation) + { + if (_rootId != null) + { + throw new IllegalConfigurationException("The store has been opened already"); + } + if (!IN_MEMORY.equals(storeLocation)) + { + _storeFile = new File(storeLocation); + if ((!_storeFile.exists() || _storeFile.length() == 0) && initialStoreLocation != null) + { + copyInitialStoreFile(initialStoreLocation); + } + createOrLoadStore(); + } + else + { + if (initialStoreLocation == null) + { + createRootEntryIfNotExists(); + } + else + { + load(toURL(initialStoreLocation)); + } + } + } + + @Override + public void open(String storeLocation, ConfigurationEntryStore initialStore) + { + if (_rootId != null) + { + throw new IllegalConfigurationException("The store has been opened already"); + } + boolean copyStore = false; + if (IN_MEMORY.equals(storeLocation)) + { + copyStore = initialStore != null; + } + else + { + _storeFile = new File(storeLocation); + if ((!_storeFile.exists() || _storeFile.length() == 0) && initialStore != null) + { + createStoreFileIfNotExist(_storeFile); + copyStore = true; + } + } + if (copyStore) + { + ConfigurationEntry rootEntry = initialStore.getRootEntry(); + _rootId = rootEntry.getId(); + copyEntry(rootEntry.getId(), initialStore); + saveAsTree(); + } + else + { + createOrLoadStore(); + } + } + + @Override + public synchronized UUID[] remove(UUID... entryIds) + { + List removedIds = new ArrayList(); + boolean anyRemoved = false; + for (UUID uuid : entryIds) + { + if (_rootId.equals(uuid)) + { + throw new IllegalConfigurationException("Cannot remove root entry"); + } + } + for (UUID uuid : entryIds) + { + if (removeInternal(uuid)) + { + anyRemoved = true; + + // remove references to the entry from parent entries + for (ConfigurationEntry entry : _entries.values()) + { + if (entry.hasChild(uuid)) + { + Set children = new HashSet(entry.getChildrenIds()); + children.remove(uuid); + ConfigurationEntry referal = new ConfigurationEntry(entry.getId(), entry.getType(), + entry.getAttributes(), children, this); + _entries.put(entry.getId(), referal); + } + } + removedIds.add(uuid); + } + } + if (anyRemoved) + { + saveAsTree(); + } + return removedIds.toArray(new UUID[removedIds.size()]); + } + + @Override + public synchronized void save(ConfigurationEntry... entries) + { + boolean anySaved = false; + for (ConfigurationEntry entry : entries) + { + ConfigurationEntry oldEntry = _entries.put(entry.getId(), entry); + if (!entry.equals(oldEntry)) + { + anySaved = true; + } + } + if (anySaved) + { + saveAsTree(); + } + } + + @Override + public ConfigurationEntry getRootEntry() + { + return getEntry(_rootId); + } + + @Override + public synchronized ConfigurationEntry getEntry(UUID id) + { + return _entries.get(id); + } + + @Override + public void copyTo(String copyLocation) + { + if (_rootId == null) + { + throw new IllegalConfigurationException("The store has not been opened"); + } + File file = new File(copyLocation); + if (!file.exists()) + { + createStoreFileIfNotExist(file); + } + saveAsTree(_rootId, _entries, _objectMapper, file); + } + + @Override + public String toString() + { + return "JsonConfigurationEntryStore [_storeFile=" + _storeFile + ", _rootId=" + _rootId + "]"; + } + + private Map> buildRelationshipClassMap() + { + Map> relationships = new HashMap>(); + + Collection> children = Model.getInstance().getChildTypes(Broker.class); + for (Class childClass : children) + { + String name = childClass.getSimpleName().toLowerCase(); + String relationshipName = name + (name.endsWith("s") ? "es" : "s"); + relationships.put(relationshipName, childClass); + } + return relationships; + } + + private void createOrLoadStore() + { + if (_storeFile != null) + { + if (!_storeFile.exists() || _storeFile.length() == 0) + { + createStoreFileIfNotExist(_storeFile); + } + else + { + load(fileToURL(_storeFile)); + } + } + + createRootEntryIfNotExists(); + } + + private void createRootEntryIfNotExists() + { + if (_rootId == null) + { + // create a root entry for an empty store + ConfigurationEntry brokerEntry = new ConfigurationEntry(UUIDGenerator.generateRandomUUID(), + Broker.class.getSimpleName(), Collections. emptyMap(), Collections. emptySet(), this); + _rootId = brokerEntry.getId(); + _entries.put(_rootId, brokerEntry); + } + } + + private void load(URL url) + { + InputStream is = null; + try + { + is = url.openStream(); + JsonNode node = loadJsonNodes(is, _objectMapper); + ConfigurationEntry brokerEntry = toEntry(node, Broker.class, _entries); + _rootId = brokerEntry.getId(); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot load store from: " + url, e); + } + finally + { + if (is != null) + { + if (is != null) + { + try + { + is.close(); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot close input stream for: " + url, e); + } + } + } + } + } + + private void copyInitialStoreFile(String initialStoreLocation) + { + createStoreFileIfNotExist(_storeFile); + URL initialStoreURL = toURL(initialStoreLocation); + InputStream in = null; + try + { + in = initialStoreURL.openStream(); + FileUtils.copy(in, _storeFile); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot create store file " + _storeFile + " by copying initial store from " + initialStoreLocation , e); + } + finally + { + if (in != null) + { + try + { + in.close(); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot close initial store input stream: " + initialStoreLocation , e); + } + } + } + } + + private URL fileToURL(File storeFile) + { + URL storeURL = null; + try + { + storeURL = storeFile.toURI().toURL(); + } + catch (MalformedURLException e) + { + throw new IllegalConfigurationException("Cannot create URL for file " + storeFile, e); + } + return storeURL; + } + + private boolean removeInternal(UUID entryId) + { + ConfigurationEntry oldEntry = _entries.remove(entryId); + if (oldEntry != null) + { + Set children = oldEntry.getChildrenIds(); + if (children != null && !children.isEmpty()) + { + for (UUID childId : children) + { + removeInternal(childId); + } + } + return true; + } + return false; + } + + private void saveAsTree() + { + if (_storeFile != null) + { + saveAsTree(_rootId, _entries, _objectMapper, _storeFile); + } + } + + private void saveAsTree(UUID rootId, Map entries, ObjectMapper mapper, File file) + { + Map tree = toTree(rootId, entries); + try + { + mapper.writeValue(file, tree); + } + catch (JsonGenerationException e) + { + throw new IllegalConfigurationException("Cannot generate json!", e); + } + catch (JsonMappingException e) + { + throw new IllegalConfigurationException("Cannot map objects for json serialization!", e); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot save configuration into " + file + "!", e); + } + } + + private Map toTree(UUID rootId, Map entries) + { + ConfigurationEntry entry = entries.get(rootId); + if (entry == null || !entry.getId().equals(rootId)) + { + throw new IllegalConfigurationException("Cannot find entry with id " + rootId + "!"); + } + Map tree = new TreeMap(); + Map attributes = entry.getAttributes(); + if (attributes != null) + { + tree.putAll(attributes); + } + tree.put(ID, entry.getId()); + tree.put(TYPE, entry.getType()); + Set childrenIds = entry.getChildrenIds(); + if (childrenIds != null && !childrenIds.isEmpty()) + { + for (UUID relationship : childrenIds) + { + ConfigurationEntry child = entries.get(relationship); + if (child != null) + { + String relationshipName = child.getType().toLowerCase() + "s"; + + @SuppressWarnings("unchecked") + Collection> children = (Collection>) tree.get(relationshipName); + if (children == null) + { + children = new ArrayList>(); + tree.put(relationshipName, children); + } + Map childAsMap = toTree(relationship, entries); + children.add(childAsMap); + } + } + } + return tree; + } + + private JsonNode loadJsonNodes(InputStream is, ObjectMapper mapper) + { + JsonNode root = null; + try + { + root = mapper.readTree(is); + } + catch (JsonProcessingException e) + { + throw new IllegalConfigurationException("Cannot parse json", e); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot read json", e); + } + return root; + } + + private ConfigurationEntry toEntry(JsonNode parent, Class expectedConfiguredObjectClass, Map entries) + { + Map attributes = null; + Set childrenIds = new TreeSet(); + Iterator fieldNames = parent.getFieldNames(); + String type = null; + String idAsString = null; + while (fieldNames.hasNext()) + { + String fieldName = fieldNames.next(); + JsonNode fieldNode = parent.get(fieldName); + if (fieldName.equals(ID)) + { + idAsString = fieldNode.asText(); + } + else if (fieldName.equals(TYPE)) + { + type = fieldNode.asText(); + } + else if (fieldNode.isArray()) + { + // array containing either broker children or attribute values + Iterator elements = fieldNode.getElements(); + List fieldValues = null; + while (elements.hasNext()) + { + JsonNode element = elements.next(); + if (element.isObject()) + { + Class expectedChildConfiguredObjectClass = _relationshipClasses.get(fieldName); + // assuming it is a child node + ConfigurationEntry entry = toEntry(element, expectedChildConfiguredObjectClass, entries); + childrenIds.add(entry.getId()); + } + else + { + if (fieldValues == null) + { + fieldValues = new ArrayList(); + } + fieldValues.add(toObject(element)); + } + } + if (fieldValues != null) + { + Object[] array = fieldValues.toArray(new Object[fieldValues.size()]); + attributes.put(fieldName, array); + } + } + else if (fieldNode.isObject()) + { + // ignore, in-line objects are not supported yet + } + else + { + // primitive attribute + Object value = toObject(fieldNode); + if (attributes == null) + { + attributes = new HashMap(); + } + attributes.put(fieldName, value); + } + } + + if (type == null) + { + if (expectedConfiguredObjectClass == null) + { + throw new IllegalConfigurationException("Type attribute is not provided for configuration entry " + parent); + } + else + { + type = expectedConfiguredObjectClass.getSimpleName(); + } + } + String name = null; + if (attributes != null) + { + name = (String) attributes.get(ATTRIBUTE_NAME); + } + if ((name == null || "".equals(name))) + { + if (expectedConfiguredObjectClass == Broker.class) + { + name = DEFAULT_BROKER_NAME; + } + else + { + throw new IllegalConfigurationException("Name attribute is not provided for configuration entry " + parent); + } + } + UUID id = null; + if (idAsString == null) + { + if (expectedConfiguredObjectClass == Broker.class) + { + id = UUIDGenerator.generateRandomUUID(); + } + else + { + id = UUIDGenerator.generateBrokerChildUUID(type, name); + } + } + else + { + try + { + id = UUID.fromString(idAsString); + } + catch (Exception e) + { + throw new IllegalConfigurationException( + "ID attribute value does not conform to UUID format for configuration entry " + parent); + } + } + ConfigurationEntry entry = new ConfigurationEntry(id, type, attributes, childrenIds, this); + if (entries.containsKey(id)) + { + throw new IllegalConfigurationException("Duplicate id is found: " + id + + "! The following configuration entries have the same id: " + entries.get(id) + ", " + entry); + } + entries.put(id, entry); + return entry; + } + + private Object toObject(JsonNode node) + { + if (node.isValueNode()) + { + if (node.isBoolean()) + { + return node.asBoolean(); + } + else if (node.isDouble()) + { + return node.asDouble(); + } + else if (node.isInt()) + { + return node.asInt(); + } + else if (node.isLong()) + { + return node.asLong(); + } + else if (node.isNull()) + { + return null; + } + else + { + return Strings.expand(node.asText()); + } + } + else if (node.isArray()) + { + return toArray(node); + } + else if (node.isObject()) + { + return toMap(node); + } + else + { + throw new IllegalConfigurationException("Unexpected node: " + node); + } + } + + private Map toMap(JsonNode node) + { + Map object = new TreeMap(); + Iterator fieldNames = node.getFieldNames(); + while (fieldNames.hasNext()) + { + String name = fieldNames.next(); + Object value = toObject(node.get(name)); + object.put(name, value); + } + return object; + } + + private Object toArray(JsonNode node) + { + ArrayNode arrayNode = (ArrayNode) node; + Object[] array = new Object[arrayNode.size()]; + Iterator elements = arrayNode.getElements(); + for (int i = 0; i < array.length; i++) + { + array[i] = toObject(elements.next()); + } + return array; + } + + /* + * Initial store location can be URL or absolute path + */ + private URL toURL(String location) + { + URL url = null; + try + { + url = new URL(location); + } + catch (MalformedURLException e) + { + File locationFile = new File(location); + url = fileToURL(locationFile); + } + return url; + } + + private void createStoreFileIfNotExist(File file) + { + File parent = file.getParentFile(); + if (!parent.exists()) + { + if (!parent.mkdirs()) + { + throw new IllegalConfigurationException("Cannot create folders " + parent); + } + } + try + { + file.createNewFile(); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot create file " + file, e); + } + } + + private void copyEntry(UUID entryId, ConfigurationEntryStore initialStore) + { + ConfigurationEntry entry = initialStore.getEntry(entryId); + if (entry != null) + { + if (_entries.containsKey(entryId)) + { + throw new IllegalConfigurationException("Duplicate id is found: " + entryId + + "! The following configuration entries have the same id: " + _entries.get(entryId) + ", " + entry); + } + _entries.put(entryId, entry); + Set children = entry.getChildrenIds(); + if (children != null) + { + for (UUID uuid : children) + { + copyEntry(uuid, initialStore); + } + } + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java new file mode 100644 index 0000000000..e7c474bf55 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandler.java @@ -0,0 +1,327 @@ +package org.apache.qpid.server.configuration.store; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.BrokerOptions; +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.util.MapValueConverter; + +public class ManagementModeStoreHandler implements ConfigurationEntryStore +{ + private static final Logger LOGGER = Logger.getLogger(ManagementModeStoreHandler.class); + + private static final String MANAGEMENT_MODE_PORT_PREFIX = "MANAGEMENT-MODE-PORT-"; + private static final String PORT_TYPE = Port.class.getSimpleName(); + private static final String VIRTUAL_HOST_TYPE = VirtualHost.class.getSimpleName(); + private static final String ATTRIBUTE_STATE = VirtualHost.STATE; + + private final ConfigurationEntryStore _store; + private final Map _cliEntries; + private final Map _quiescedEntries; + private final UUID _rootId; + + public ManagementModeStoreHandler(ConfigurationEntryStore store, BrokerOptions options) + { + ConfigurationEntry storeRoot = store.getRootEntry(); + _store = store; + _rootId = storeRoot.getId(); + _cliEntries = createPortsFromCommadLineOptions(options); + _quiescedEntries = quiesceEntries(storeRoot, options); + } + + @Override + public void open(String storeLocation) + { + throw new IllegalStateException("The store should be already opened"); + } + + @Override + public void open(String storeLocation, String initialStoreLocation) + { + throw new IllegalStateException("The store should be already opened"); + } + + @Override + public void open(String storeLocation, ConfigurationEntryStore initialStore) + { + throw new IllegalStateException("The store should be already opened"); + } + + @Override + public ConfigurationEntry getRootEntry() + { + return getEntry(_rootId); + } + + @Override + public ConfigurationEntry getEntry(UUID id) + { + synchronized (_store) + { + if (_cliEntries.containsKey(id)) + { + return _cliEntries.get(id); + } + + ConfigurationEntry entry = _store.getEntry(id); + if (_quiescedEntries.containsKey(id)) + { + entry = createEntryWithState(entry, State.QUIESCED); + } + else if (id == _rootId) + { + entry = createRootWithCLIEntries(entry); + } + return entry; + } + } + + @Override + public void save(ConfigurationEntry... entries) + { + synchronized (_store) + { + ConfigurationEntry[] entriesToSave = new ConfigurationEntry[entries.length]; + + for (int i = 0; i < entries.length; i++) + { + ConfigurationEntry entry = entries[i]; + UUID id = entry.getId(); + if (_cliEntries.containsKey(id)) + { + throw new IllegalConfigurationException("Cannot save configuration provided as command line argument:" + + entry); + } + else if (_quiescedEntries.containsKey(id)) + { + // save entry with the original state + entry = createEntryWithState(entry, _quiescedEntries.get(ATTRIBUTE_STATE)); + } + else if (_rootId.equals(id)) + { + // save root without command line entries + Set childrenIds = new HashSet(entry.getChildrenIds()); + if (!_cliEntries.isEmpty()) + { + childrenIds.removeAll(_cliEntries.entrySet()); + } + HashMap attributes = new HashMap(entry.getAttributes()); + entry = new ConfigurationEntry(entry.getId(), entry.getType(), attributes, childrenIds, this); + } + entriesToSave[i] = entry; + } + + _store.save(entriesToSave); + } + } + + @Override + public UUID[] remove(UUID... entryIds) + { + synchronized (_store) + { + for (UUID id : entryIds) + { + if (_cliEntries.containsKey(id)) + { + throw new IllegalConfigurationException("Cannot change configuration for command line entry:" + + _cliEntries.get(id)); + } + } + UUID[] result = _store.remove(entryIds); + for (UUID id : entryIds) + { + if (_quiescedEntries.containsKey(id)) + { + _quiescedEntries.remove(id); + } + } + return result; + } + } + + @Override + public void copyTo(String copyLocation) + { + synchronized (_store) + { + _store.copyTo(copyLocation); + } + } + + private Map createPortsFromCommadLineOptions(BrokerOptions options) + { + int managementModeRmiPort = options.getManagementModeRmiPort(); + if (managementModeRmiPort < 0) + { + throw new IllegalConfigurationException("Invalid rmi port is specified: " + managementModeRmiPort); + } + int managementModeConnectorPort = options.getManagementModeConnectorPort(); + if (managementModeConnectorPort < 0) + { + throw new IllegalConfigurationException("Invalid connector port is specified: " + managementModeConnectorPort); + } + int managementModeHttpPort = options.getManagementModeHttpPort(); + if (managementModeHttpPort < 0) + { + throw new IllegalConfigurationException("Invalid http port is specified: " + managementModeHttpPort); + } + Map cliEntries = new HashMap(); + if (managementModeRmiPort != 0) + { + ConfigurationEntry entry = createCLIPortEntry(managementModeRmiPort, Protocol.RMI); + cliEntries.put(entry.getId(), entry); + if (managementModeConnectorPort == 0) + { + ConfigurationEntry connectorEntry = createCLIPortEntry(managementModeRmiPort + 100, Protocol.JMX_RMI); + cliEntries.put(connectorEntry.getId(), connectorEntry); + } + } + if (managementModeConnectorPort != 0) + { + ConfigurationEntry entry = createCLIPortEntry(managementModeConnectorPort, Protocol.JMX_RMI); + cliEntries.put(entry.getId(), entry); + } + if (managementModeHttpPort != 0) + { + ConfigurationEntry entry = createCLIPortEntry(managementModeHttpPort, Protocol.HTTP); + cliEntries.put(entry.getId(), entry); + } + return cliEntries; + } + + private ConfigurationEntry createCLIPortEntry(int port, Protocol protocol) + { + Map attributes = new HashMap(); + attributes.put(Port.PORT, port); + attributes.put(Port.PROTOCOLS, Collections.singleton(protocol)); + attributes.put(Port.NAME, MANAGEMENT_MODE_PORT_PREFIX + protocol.name()); + ConfigurationEntry portEntry = new ConfigurationEntry(UUID.randomUUID(), PORT_TYPE, attributes, + Collections. emptySet(), this); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Add management mode port configuration " + portEntry + " for port " + port + " and protocol " + + protocol); + } + return portEntry; + } + + private ConfigurationEntry createRootWithCLIEntries(ConfigurationEntry storeRoot) + { + Set childrenIds = new HashSet(storeRoot.getChildrenIds()); + if (!_cliEntries.isEmpty()) + { + childrenIds.addAll(_cliEntries.keySet()); + } + ConfigurationEntry root = new ConfigurationEntry(storeRoot.getId(), storeRoot.getType(), new HashMap( + storeRoot.getAttributes()), childrenIds, this); + return root; + } + + private Map quiesceEntries(ConfigurationEntry storeRoot, BrokerOptions options) + { + Map quiescedEntries = new HashMap(); + Set childrenIds; + int managementModeRmiPort = options.getManagementModeRmiPort(); + int managementModeConnectorPort = options.getManagementModeConnectorPort(); + int managementModeHttpPort = options.getManagementModeHttpPort(); + childrenIds = storeRoot.getChildrenIds(); + for (UUID id : childrenIds) + { + ConfigurationEntry entry = _store.getEntry(id); + String entryType = entry.getType(); + Map attributes = entry.getAttributes(); + boolean quiesce = false; + if (VIRTUAL_HOST_TYPE.equals(entryType)) + { + quiesce = true; + } + else if (PORT_TYPE.equalsIgnoreCase(entryType)) + { + if (attributes == null) + { + throw new IllegalConfigurationException("Port attributes are not set in " + entry); + } + Set protocols = getPortProtocolsAttribute(attributes); + if (protocols == null) + { + quiesce = true; + } + else + { + for (Protocol protocol : protocols) + { + switch (protocol) + { + case JMX_RMI: + quiesce = managementModeConnectorPort > 0 || managementModeRmiPort > 0; + break; + case RMI: + quiesce = managementModeRmiPort > 0; + break; + case HTTP: + case HTTPS: + quiesce = managementModeHttpPort > 0; + break; + default: + quiesce = true; + } + } + } + } + if (quiesce) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Management mode quiescing entry " + entry); + } + + // save original state + quiescedEntries.put(entry.getId(), attributes.get(ATTRIBUTE_STATE)); + } + } + return quiescedEntries; + } + + private Set getPortProtocolsAttribute(Map attributes) + { + Object object = attributes.get(Port.PROTOCOLS); + if (object == null) + { + return null; + } + return MapValueConverter.getEnumSetAttribute(Port.PROTOCOLS, attributes, Protocol.class); + } + + private ConfigurationEntry createEntryWithState(ConfigurationEntry entry, Object state) + { + Map attributes = new HashMap(entry.getAttributes()); + if (state == null) + { + attributes.remove(ATTRIBUTE_STATE); + } + else + { + attributes.put(ATTRIBUTE_STATE, state); + } + Set originalChildren = entry.getChildrenIds(); + Set children = null; + if (originalChildren != null) + { + children = new HashSet(originalChildren); + } + return new ConfigurationEntry(entry.getId(), entry.getType(), attributes, children, entry.getStore()); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java new file mode 100644 index 0000000000..813702d0a6 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java @@ -0,0 +1,205 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.store; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfigurationChangeListener; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; + +public class StoreConfigurationChangeListener implements ConfigurationChangeListener +{ + private ConfigurationEntryStore _store; + + public StoreConfigurationChangeListener(ConfigurationEntryStore store) + { + super(); + _store = store; + } + + @Override + public void stateChanged(ConfiguredObject object, State oldState, State newState) + { + if (newState == State.DELETED) + { + _store.remove(object.getId()); + object.removeChangeListener(this); + } + } + + @Override + public void childAdded(ConfiguredObject object, ConfiguredObject child) + { + // exclude VirtualHost children from storing in broker store + if (!(object instanceof VirtualHost)) + { + child.addChangeListener(this); + ConfigurationEntry parentEntry = toConfigurationEntry(object); + ConfigurationEntry childEntry = toConfigurationEntry(child); + _store.save(parentEntry, childEntry); + } + + } + + @Override + public void childRemoved(ConfiguredObject object, ConfiguredObject child) + { + _store.save(toConfigurationEntry(object)); + } + + @Override + public void attributeSet(ConfiguredObject object, String attrinuteName, Object oldAttributeValue, Object newAttributeValue) + { + _store.save(toConfigurationEntry(object)); + } + + private ConfigurationEntry toConfigurationEntry(ConfiguredObject object) + { + Class objectType = getConfiguredObjectType(object); + Set childrenIds = getChildernIds(object, objectType); + ConfigurationEntry entry = new ConfigurationEntry(object.getId(), objectType.getSimpleName(), + object.getActualAttributes(), childrenIds, _store); + return entry; + } + + private Set getChildernIds(ConfiguredObject object, Class objectType) + { + // Virtual Host children's IDs should not be stored in broker store + if (object instanceof VirtualHost) + { + return Collections.emptySet(); + } + Set childrenIds = new TreeSet(); + Collection> childClasses = Model.getInstance().getChildTypes(objectType); + if (childClasses != null) + { + for (Class childClass : childClasses) + { + Collection children = object.getChildren(childClass); + if (children != null) + { + for (ConfiguredObject childObject : children) + { + childrenIds.add(childObject.getId()); + } + } + } + } + return childrenIds; + } + + private Class getConfiguredObjectType(ConfiguredObject object) + { + if (object instanceof Broker) + { + return Broker.class; + } + return getConfiguredObjectTypeFromImplementedInterfaces(object.getClass()); + } + + @SuppressWarnings("unchecked") + private Class getConfiguredObjectTypeFromImplementedInterfaces(Class objectClass) + { + // get all implemented interfaces extending ConfiguredObject + Set> interfaces = getImplementedInterfacesExtendingSuper(objectClass, ConfiguredObject.class); + + if (interfaces.size() == 0) + { + throw new RuntimeException("Can not identify the configured object type"); + } + + if (interfaces.size() == 1) + { + return (Class)interfaces.iterator().next(); + } + + Set> superInterfaces = new HashSet>(); + + // find all super interfaces + for (Class interfaceClass : interfaces) + { + for (Class interfaceClass2 : interfaces) + { + if (interfaceClass != interfaceClass2) + { + if (interfaceClass.isAssignableFrom(interfaceClass2)) + { + superInterfaces.add(interfaceClass); + } + } + } + } + + // remove super interfaces + for (Class superInterface : superInterfaces) + { + interfaces.remove(superInterface); + } + + if (interfaces.size() == 1) + { + return (Class)interfaces.iterator().next(); + } + else + { + throw new RuntimeException("Can not identify the configured object type as an it implements" + + " more than one configured object interfaces: " + interfaces); + } + + } + + private Set> getImplementedInterfacesExtendingSuper(Class classInstance, Class superInterface) + { + Set> interfaces = new HashSet>(); + Class[] classInterfaces = classInstance.getInterfaces(); + for (Class interfaceClass : classInterfaces) + { + if (interfaceClass!= superInterface && superInterface.isAssignableFrom(interfaceClass)) + { + interfaces.add(interfaceClass); + } + } + Class superClass = classInstance.getSuperclass(); + if (superClass != null) + { + Set> superClassInterfaces = getImplementedInterfacesExtendingSuper(superClass, superInterface); + interfaces.addAll(superClassInterfaces); + } + return interfaces; + } + + @Override + public String toString() + { + return "StoreConfigurationChangeListener [store=" + _store + "]"; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/JsonConfigurationStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/JsonConfigurationStoreFactory.java new file mode 100644 index 0000000000..e37e58b840 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/store/factory/JsonConfigurationStoreFactory.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.store.factory; + +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.ConfigurationStoreFactory; +import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore; + +public class JsonConfigurationStoreFactory implements ConfigurationStoreFactory +{ + @Override + public ConfigurationEntryStore createStore() + { + return new JsonConfigurationEntryStore(); + } + + @Override + public String getStoreType() + { + return JsonConfigurationEntryStore.STORE_TYPE; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/ChangeStateTask.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/ChangeStateTask.java new file mode 100644 index 0000000000..b6de1e136a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/ChangeStateTask.java @@ -0,0 +1,67 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.updater; + +import java.util.concurrent.Callable; + +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.State; + +public final class ChangeStateTask implements Callable +{ + private ConfiguredObject _object; + private State _expectedState; + private State _desiredState; + + public ChangeStateTask(ConfiguredObject object, State expectedState, State desiredState) + { + _object = object; + _expectedState = expectedState; + _desiredState = desiredState; + } + + public ConfiguredObject getObject() + { + return _object; + } + + public State getExpectedState() + { + return _expectedState; + } + + public State getDesiredState() + { + return _desiredState; + } + + @Override + public State call() + { + return _object.setDesiredState(_expectedState, _desiredState); + } + + @Override + public String toString() + { + return "ChangeStateTask [object=" + _object + ", expectedState=" + _expectedState + ", desiredState=" + _desiredState + "]"; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/CreateChildTask.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/CreateChildTask.java new file mode 100644 index 0000000000..d3a8f5b797 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/CreateChildTask.java @@ -0,0 +1,78 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.updater; + +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.Callable; + +import org.apache.qpid.server.model.ConfiguredObject; + +public final class CreateChildTask implements Callable +{ + private ConfiguredObject _object; + private Class _childClass; + private Map _attributes; + private ConfiguredObject[] _otherParents; + + public CreateChildTask(ConfiguredObject object, Class childClass, Map attributes, + ConfiguredObject... otherParents) + { + _object = object; + _childClass = childClass; + _attributes = attributes; + _otherParents = otherParents; + } + + public ConfiguredObject getObject() + { + return _object; + } + + public Class getChildClass() + { + return _childClass; + } + + public Map getAttributes() + { + return _attributes; + } + + public ConfiguredObject[] getOtherParents() + { + return _otherParents; + } + + @Override + public ConfiguredObject call() + { + return _object.createChild(_childClass, _attributes, _otherParents); + } + + @Override + public String toString() + { + return "CreateChildTask [object=" + _object + ", childClass=" + _childClass + ", attributes=" + _attributes + + ", otherParents=" + Arrays.toString(_otherParents) + "]"; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/SetAttributeTask.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/SetAttributeTask.java new file mode 100644 index 0000000000..94649434e6 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/SetAttributeTask.java @@ -0,0 +1,74 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.updater; + +import java.util.concurrent.Callable; + +import org.apache.qpid.server.model.ConfiguredObject; + +public final class SetAttributeTask implements Callable +{ + private ConfiguredObject _object; + private String _attributeName; + private Object _expectedValue; + private Object _desiredValue; + + public SetAttributeTask(ConfiguredObject object, String attributeName, Object expectedValue, Object desiredValue) + { + _object = object; + _attributeName = attributeName; + _expectedValue = expectedValue; + _desiredValue = desiredValue; + } + + public ConfiguredObject getObject() + { + return _object; + } + + public String getAttributeName() + { + return _attributeName; + } + + public Object getExpectedValue() + { + return _expectedValue; + } + + public Object getDesiredValue() + { + return _desiredValue; + } + + @Override + public Object call() + { + return _object.setAttribute(_attributeName, _expectedValue, _desiredValue); + } + + @Override + public String toString() + { + return "SetAttributeTask [object=" + _object + ", attributeName=" + _attributeName + ", expectedValue=" + _expectedValue + + ", desiredValue=" + _desiredValue + "]"; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutor.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutor.java new file mode 100644 index 0000000000..671104d413 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/updater/TaskExecutor.java @@ -0,0 +1,324 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.updater; + +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.RunnableFuture; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import javax.security.auth.Subject; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.security.SecurityManager; + +public class TaskExecutor +{ + private static final String TASK_EXECUTION_THREAD_NAME = "Broker-Configuration-Thread"; + private static final Logger LOGGER = Logger.getLogger(TaskExecutor.class); + + private volatile Thread _taskThread; + private final AtomicReference _state; + private volatile ExecutorService _executor; + + public TaskExecutor() + { + _state = new AtomicReference(State.INITIALISING); + } + + public State getState() + { + return _state.get(); + } + + public void start() + { + if (_state.compareAndSet(State.INITIALISING, State.ACTIVE)) + { + LOGGER.debug("Starting task executor"); + _executor = Executors.newFixedThreadPool(1, new ThreadFactory() + { + @Override + public Thread newThread(Runnable r) + { + _taskThread = new Thread(r, TASK_EXECUTION_THREAD_NAME); + return _taskThread; + } + }); + LOGGER.debug("Task executor is started"); + } + } + + public void stopImmediately() + { + if (_state.compareAndSet(State.ACTIVE, State.STOPPED)) + { + ExecutorService executor = _executor; + if (executor != null) + { + LOGGER.debug("Stopping task executor immediately"); + List cancelledTasks = executor.shutdownNow(); + if (cancelledTasks != null) + { + for (Runnable runnable : cancelledTasks) + { + if (runnable instanceof RunnableFuture) + { + ((RunnableFuture) runnable).cancel(true); + } + } + } + _executor = null; + _taskThread = null; + LOGGER.debug("Task executor was stopped immediately. Number of unfinished tasks: " + cancelledTasks.size()); + } + } + } + + public void stop() + { + if (_state.compareAndSet(State.ACTIVE, State.STOPPED)) + { + ExecutorService executor = _executor; + if (executor != null) + { + LOGGER.debug("Stopping task executor"); + executor.shutdown(); + _executor = null; + _taskThread = null; + LOGGER.debug("Task executor is stopped"); + } + } + } + + Future submit(Callable task) + { + checkState(); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Submitting task: " + task); + } + Future future = null; + if (isTaskExecutorThread()) + { + Object result = executeTaskAndHandleExceptions(task); + return new ImmediateFuture(result); + } + else + { + future = _executor.submit(new CallableWrapper(task)); + } + return future; + } + + public Object submitAndWait(Callable task) throws CancellationException + { + try + { + Future future = submit(task); + return future.get(); + } + catch (InterruptedException e) + { + throw new RuntimeException("Task execution was interrupted: " + task, e); + } + catch (ExecutionException e) + { + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException) + { + throw (RuntimeException) cause; + } + else if (cause instanceof Exception) + { + throw new RuntimeException("Failed to execute user task: " + task, cause); + } + else if (cause instanceof Error) + { + throw (Error) cause; + } + else + { + throw new RuntimeException("Failed to execute user task: " + task, cause); + } + } + } + + public boolean isTaskExecutorThread() + { + return Thread.currentThread() == _taskThread; + } + + private void checkState() + { + if (_state.get() != State.ACTIVE) + { + throw new IllegalStateException("Task executor is not in ACTIVE state"); + } + } + + private Object executeTaskAndHandleExceptions(Callable userTask) + { + try + { + return executeTask(userTask); + } + catch (Exception e) + { + if (e instanceof RuntimeException) + { + throw (RuntimeException) e; + } + throw new RuntimeException("Failed to execute user task: " + userTask, e); + } + } + + private Object executeTask(Callable userTask) throws Exception + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Performing task " + userTask); + } + Object result = userTask.call(); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Task " + userTask + " is performed successfully with result:" + result); + } + return result; + } + + private class CallableWrapper implements Callable + { + private Callable _userTask; + private Subject _securityManagerSubject; + private LogActor _actor; + private Subject _contextSubject; + + public CallableWrapper(Callable userWork) + { + _userTask = userWork; + _securityManagerSubject = SecurityManager.getThreadSubject(); + _actor = CurrentActor.get(); + _contextSubject = Subject.getSubject(AccessController.getContext()); + } + + @Override + public Object call() throws Exception + { + SecurityManager.setThreadSubject(_securityManagerSubject); + CurrentActor.set(_actor); + + try + { + Object result = null; + try + { + result = Subject.doAs(_contextSubject, new PrivilegedExceptionAction() + { + @Override + public Object run() throws Exception + { + return executeTask(_userTask); + } + }); + } + catch (PrivilegedActionException e) + { + throw e.getException(); + } + return result; + } + finally + { + try + { + CurrentActor.remove(); + } + catch (Exception e) + { + LOGGER.warn("Unxpected exception on current actor removal", e); + } + try + { + SecurityManager.setThreadSubject(null); + } + catch (Exception e) + { + LOGGER.warn("Unxpected exception on nullifying of subject for a security manager", e); + } + } + } + } + + private class ImmediateFuture implements Future + { + private Object _result; + + public ImmediateFuture(Object result) + { + super(); + this._result = result; + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) + { + return false; + } + + @Override + public boolean isCancelled() + { + return false; + } + + @Override + public boolean isDone() + { + return true; + } + + @Override + public Object get() + { + return _result; + } + + @Override + public Object get(long timeout, TimeUnit unit) + { + return get(); + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index 512a8c6996..246e056f0b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java @@ -23,14 +23,12 @@ package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.ExchangeConfigType; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ExchangeMessages; import org.apache.qpid.server.logging.subjects.ExchangeLogSubject; import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueRegistry; @@ -86,8 +84,6 @@ public abstract class AbstractExchange implements Exchange //TODO : persist creation time private long _createTime = System.currentTimeMillis(); - private UUID _qmfId; - public AbstractExchange(final ExchangeType type) { _type = type; @@ -113,19 +109,12 @@ public abstract class AbstractExchange implements Exchange _ticket = ticket; _id = id; - _qmfId = getConfigStore().createId(); - getConfigStore().addConfiguredObject(this); _logSubject = new ExchangeLogSubject(this, this.getVirtualHost()); // Log Exchange creation CurrentActor.get().message(ExchangeMessages.CREATED(String.valueOf(getTypeShortString()), String.valueOf(name), durable)); } - public ConfigStore getConfigStore() - { - return getVirtualHost().getConfigStore(); - } - public boolean isDurable() { return _durable; @@ -146,7 +135,6 @@ public abstract class AbstractExchange implements Exchange if(_closed.compareAndSet(false,true)) { - getConfigStore().removeConfiguredObject(this); if(_alternateExchange != null) { _alternateExchange.removeReference(this); @@ -298,29 +286,11 @@ public abstract class AbstractExchange implements Exchange return _id; } - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public ExchangeConfigType getConfigType() - { - return ExchangeConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return _virtualHost; - } - public long getBindingCount() { return getBindings().size(); } - - public final List route(final InboundMessage message) { _receivedMessageCount.incrementAndGet(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java index 5058f91995..5e6e36d330 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java @@ -27,10 +27,9 @@ import org.apache.qpid.AMQSecurityException; import org.apache.qpid.AMQUnknownExchangeType; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.qmf.ManagementExchange; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.ArrayList; @@ -41,42 +40,72 @@ import java.util.UUID; public class DefaultExchangeFactory implements ExchangeFactory { - private static final Logger _logger = Logger.getLogger(DefaultExchangeFactory.class); public static final String DEFAULT_DLE_NAME_SUFFIX = "_DLE"; - private Map> _exchangeClassMap = new HashMap>(); + private static final Logger LOGGER = Logger.getLogger(DefaultExchangeFactory.class); + + private static final AMQShortString[] BASE_EXCHANGE_TYPES = + new AMQShortString[]{ExchangeDefaults.DIRECT_EXCHANGE_CLASS, + ExchangeDefaults.FANOUT_EXCHANGE_CLASS, + ExchangeDefaults.HEADERS_EXCHANGE_CLASS, + ExchangeDefaults.TOPIC_EXCHANGE_CLASS}; + private final VirtualHost _host; + private Map> _exchangeClassMap = new HashMap>(); public DefaultExchangeFactory(VirtualHost host) { _host = host; - registerExchangeType(DirectExchange.TYPE); - registerExchangeType(TopicExchange.TYPE); - registerExchangeType(HeadersExchange.TYPE); - registerExchangeType(FanoutExchange.TYPE); - registerExchangeType(ManagementExchange.TYPE); + + @SuppressWarnings("rawtypes") + Iterable exchangeTypes = loadExchangeTypes(); + for (ExchangeType exchangeType : exchangeTypes) + { + AMQShortString typeName = exchangeType.getName(); + + if(LOGGER.isDebugEnabled()) + { + LOGGER.debug("Registering exchange type '" + typeName + "' using class '" + exchangeType.getClass().getName() + "'"); + } + + if(_exchangeClassMap.containsKey(typeName)) + { + ExchangeType existingType = _exchangeClassMap.get(typeName); + + throw new IllegalStateException("ExchangeType with type name '" + typeName + "' is already registered using class '" + + existingType.getClass().getName() + "', can not register class '" + + exchangeType.getClass().getName() + "'"); + } + + _exchangeClassMap.put(typeName, exchangeType); + } + + for(AMQShortString type : BASE_EXCHANGE_TYPES) + { + if(!_exchangeClassMap.containsKey(type)) + { + throw new IllegalStateException("Did not find expected exchange type: " + type.asString()); + } + } } - public void registerExchangeType(ExchangeType type) + @SuppressWarnings("rawtypes") + protected Iterable loadExchangeTypes() { - _exchangeClassMap.put(type.getName(), type); + return new QpidServiceLoader().atLeastOneInstanceOf(ExchangeType.class); } public Collection> getRegisteredTypes() { return _exchangeClassMap.values(); } - + public Collection> getPublicCreatableTypes() { Collection> publicTypes = new ArrayList>(); publicTypes.addAll(_exchangeClassMap.values()); - //Remove the ManagementExchange type if present, as these - //are private and cannot be created by external means - publicTypes.remove(ManagementExchange.TYPE); - return publicTypes; } @@ -120,42 +149,4 @@ public class DefaultExchangeFactory implements ExchangeFactory Exchange e = exchType.newInstance(id, _host, exchange, durable, ticket, autoDelete); return e; } - - public void initialise(VirtualHostConfiguration hostConfig) - { - - if (hostConfig == null) - { - return; - } - - for(Object className : hostConfig.getCustomExchanges()) - { - try - { - ExchangeType exchangeType = ApplicationRegistry.getInstance().getPluginManager().getExchanges().get(String.valueOf(className)); - if (exchangeType == null) - { - _logger.error("No such custom exchange class found: \""+String.valueOf(className)+"\""); - continue; - } - Class exchangeTypeClass = exchangeType.getClass(); - ExchangeType type = exchangeTypeClass.newInstance(); - registerExchangeType(type); - } - catch (ClassCastException classCastEx) - { - _logger.error("No custom exchange class: \""+String.valueOf(className)+"\" cannot be registered as it does not extend class \""+ExchangeType.class+"\""); - } - catch (IllegalAccessException e) - { - _logger.error("Cannot create custom exchange class: \""+String.valueOf(className)+"\"",e); - } - catch (InstantiationException e) - { - _logger.error("Cannot create custom exchange class: \""+String.valueOf(className)+"\"",e); - } - } - - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java index 07813b073b..9cce8d640b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java @@ -26,6 +26,7 @@ import org.apache.qpid.AMQSecurityException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java index 92326412c1..fc6ce15bc4 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java @@ -20,30 +20,22 @@ */ package org.apache.qpid.server.exchange; -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.virtualhost.VirtualHost; -import javax.management.JMException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; public class DirectExchange extends AbstractExchange { - private static final Logger _logger = Logger.getLogger(DirectExchange.class); - private static final class BindingSet { private CopyOnWriteArraySet _bindings = new CopyOnWriteArraySet(); @@ -55,7 +47,6 @@ public class DirectExchange extends AbstractExchange recalculateQueues(); } - public synchronized void removeBinding(Binding binding) { _bindings.remove(binding); @@ -91,36 +82,7 @@ public class DirectExchange extends AbstractExchange private final ConcurrentHashMap _bindingsByKey = new ConcurrentHashMap(); - public static final ExchangeType TYPE = new ExchangeType() - { - - public AMQShortString getName() - { - return ExchangeDefaults.DIRECT_EXCHANGE_CLASS; - } - - public Class getExchangeClass() - { - return DirectExchange.class; - } - - public DirectExchange newInstance(UUID id, VirtualHost host, - AMQShortString name, - boolean durable, - int ticket, - boolean autoDelete) throws AMQException - { - DirectExchange exch = new DirectExchange(); - exch.initialise(id, host,name,durable,ticket,autoDelete); - return exch; - } - - public AMQShortString getDefaultExchangeName() - { - return ExchangeDefaults.DIRECT_EXCHANGE_NAME; - } - }; - + public static final ExchangeType TYPE = new DirectExchangeType(); public DirectExchange() { diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java new file mode 100644 index 0000000000..096d5265ed --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java @@ -0,0 +1,53 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.exchange; + +import java.util.UUID; + +import org.apache.qpid.AMQException; +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class DirectExchangeType implements ExchangeType +{ + public AMQShortString getName() + { + return ExchangeDefaults.DIRECT_EXCHANGE_CLASS; + } + + public DirectExchange newInstance(UUID id, VirtualHost host, + AMQShortString name, + boolean durable, + int ticket, + boolean autoDelete) throws AMQException + { + DirectExchange exch = new DirectExchange(); + exch.initialise(id, host,name,durable,ticket,autoDelete); + return exch; + } + + public AMQShortString getDefaultExchangeName() + { + return ExchangeDefaults.DIRECT_EXCHANGE_NAME; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java index 762686e68d..4bafb04c33 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java @@ -26,8 +26,8 @@ import org.apache.qpid.AMQSecurityException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.ExchangeConfig; import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -38,9 +38,23 @@ import java.util.List; import java.util.Map; import java.util.UUID; -public interface Exchange extends ExchangeReferrer, ExchangeConfig +public interface Exchange extends ExchangeReferrer { + String getName(); + + ExchangeType getType(); + + long getBindingCount(); + + long getByteDrops(); + + long getByteReceives(); + + long getMsgDrops(); + + long getMsgReceives(); + public interface BindingListener { void bindingAdded(Exchange exchange, Binding binding); diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java index aae4ae89bb..e602d476d9 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java @@ -22,7 +22,7 @@ package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.plugin.ExchangeType; import java.util.Collection; import java.util.UUID; @@ -34,8 +34,6 @@ public interface ExchangeFactory int ticket) throws AMQException; - void initialise(VirtualHostConfiguration hostConfig); - Collection> getRegisteredTypes(); Collection> getPublicCreatableTypes(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java index ba4f57a8e0..edb476f3aa 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java @@ -24,6 +24,7 @@ package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.store.DurableConfigurationStore; public class ExchangeInitialiser diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeType.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeType.java deleted file mode 100644 index a01e41f039..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeType.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.exchange; - -import java.util.UUID; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.virtualhost.VirtualHost; - - -public interface ExchangeType -{ - public AMQShortString getName(); - public Class getExchangeClass(); - public T newInstance(UUID id, VirtualHost host, AMQShortString name, - boolean durable, int ticket, boolean autoDelete) throws AMQException; - public AMQShortString getDefaultExchangeName(); -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java index 5f4998f77f..8c433ce985 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java @@ -22,19 +22,15 @@ package org.apache.qpid.server.exchange; import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; -import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.virtualhost.VirtualHost; -import javax.management.JMException; import java.util.ArrayList; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; public class FanoutExchange extends AbstractExchange @@ -48,35 +44,7 @@ public class FanoutExchange extends AbstractExchange */ private final ConcurrentHashMap _queues = new ConcurrentHashMap(); - public static final ExchangeType TYPE = new ExchangeType() - { - - public AMQShortString getName() - { - return ExchangeDefaults.FANOUT_EXCHANGE_CLASS; - } - - public Class getExchangeClass() - { - return FanoutExchange.class; - } - - public FanoutExchange newInstance(UUID id, VirtualHost host, - AMQShortString name, - boolean durable, - int ticket, - boolean autoDelete) throws AMQException - { - FanoutExchange exch = new FanoutExchange(); - exch.initialise(id, host, name, durable, ticket, autoDelete); - return exch; - } - - public AMQShortString getDefaultExchangeName() - { - return ExchangeDefaults.FANOUT_EXCHANGE_NAME; - } - }; + public static final ExchangeType TYPE = new FanoutExchangeType(); public FanoutExchange() { diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java new file mode 100644 index 0000000000..0371a363de --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.exchange; + +import java.util.UUID; + +import org.apache.qpid.AMQException; +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class FanoutExchangeType implements ExchangeType +{ + public AMQShortString getName() + { + return ExchangeDefaults.FANOUT_EXCHANGE_CLASS; + } + + public FanoutExchange newInstance(UUID id, VirtualHost host, AMQShortString name, + boolean durable, int ticket, boolean autoDelete) + throws AMQException + { + FanoutExchange exch = new FanoutExchange(); + exch.initialise(id, host, name, durable, ticket, autoDelete); + return exch; + } + + public AMQShortString getDefaultExchangeName() + { + return ExchangeDefaults.FANOUT_EXCHANGE_NAME; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java index 6bad59c2ae..746c8ac6bc 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java @@ -22,22 +22,18 @@ package org.apache.qpid.server.exchange; import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; -import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.virtualhost.VirtualHost; -import javax.management.JMException; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.Map; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; @@ -81,40 +77,12 @@ public class HeadersExchange extends AbstractExchange new CopyOnWriteArrayList(); - public static final ExchangeType TYPE = new ExchangeType() - { - - public AMQShortString getName() - { - return ExchangeDefaults.HEADERS_EXCHANGE_CLASS; - } - - public Class getExchangeClass() - { - return HeadersExchange.class; - } - - public HeadersExchange newInstance(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, - boolean autoDelete) throws AMQException - { - HeadersExchange exch = new HeadersExchange(); - - exch.initialise(id, host, name, durable, ticket, autoDelete); - return exch; - } - - public AMQShortString getDefaultExchangeName() - { - - return ExchangeDefaults.HEADERS_EXCHANGE_NAME; - } - }; + public static final ExchangeType TYPE = new HeadersExchangeType(); public HeadersExchange() { super(TYPE); } - public ArrayList doRoute(InboundMessage payload) diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java new file mode 100644 index 0000000000..ed4d57d0f8 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java @@ -0,0 +1,52 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.exchange; + +import java.util.UUID; + +import org.apache.qpid.AMQException; +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class HeadersExchangeType implements ExchangeType +{ + public AMQShortString getName() + { + return ExchangeDefaults.HEADERS_EXCHANGE_CLASS; + } + + public HeadersExchange newInstance(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, + boolean autoDelete) throws AMQException + { + HeadersExchange exch = new HeadersExchange(); + + exch.initialise(id, host, name, durable, ticket, autoDelete); + return exch; + } + + public AMQShortString getDefaultExchangeName() + { + + return ExchangeDefaults.HEADERS_EXCHANGE_NAME; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java index 0ce16bd3f7..6d548be508 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java @@ -27,15 +27,11 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; -import java.util.UUID; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; -import javax.management.JMException; import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; import org.apache.qpid.AMQInvalidArgumentException; import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.filter.SelectorParsingException; import org.apache.qpid.filter.selector.ParseException; import org.apache.qpid.filter.selector.TokenMgrError; @@ -49,44 +45,15 @@ import org.apache.qpid.server.exchange.topic.TopicParser; import org.apache.qpid.server.filter.JMSSelectorFilter; import org.apache.qpid.server.filter.MessageFilter; import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.Filterable; -import org.apache.qpid.server.virtualhost.VirtualHost; public class TopicExchange extends AbstractExchange { - - public static final ExchangeType TYPE = new ExchangeType() - { - - public AMQShortString getName() - { - return ExchangeDefaults.TOPIC_EXCHANGE_CLASS; - } - - public Class getExchangeClass() - { - return TopicExchange.class; - } - - public TopicExchange newInstance(UUID id, VirtualHost host, - AMQShortString name, - boolean durable, - int ticket, - boolean autoDelete) throws AMQException - { - TopicExchange exch = new TopicExchange(); - exch.initialise(id, host, name, durable, ticket, autoDelete); - return exch; - } - - public AMQShortString getDefaultExchangeName() - { - return ExchangeDefaults.TOPIC_EXCHANGE_NAME; - } - }; + public static final ExchangeType TYPE = new TopicExchangeType(); private static final Logger _logger = Logger.getLogger(TopicExchange.class); @@ -291,7 +258,7 @@ public class TopicExchange extends AbstractExchange public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue) { - Binding binding = new Binding(null, null, routingKey.toString(), queue, this, FieldTable.convertToMap(arguments)); + Binding binding = new Binding(null, routingKey.toString(), queue, this, FieldTable.convertToMap(arguments)); if (arguments == null) { @@ -314,7 +281,7 @@ public class TopicExchange extends AbstractExchange public boolean isBound(String bindingKey, Map arguments, AMQQueue queue) { - Binding binding = new Binding(null, null, bindingKey, queue, this, arguments); + Binding binding = new Binding(null, bindingKey, queue, this, arguments); if (arguments == null) { return _bindings.containsKey(binding); diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java new file mode 100644 index 0000000000..25a3549e61 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java @@ -0,0 +1,53 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.exchange; + +import java.util.UUID; + +import org.apache.qpid.AMQException; +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class TopicExchangeType implements ExchangeType +{ + public AMQShortString getName() + { + return ExchangeDefaults.TOPIC_EXCHANGE_CLASS; + } + + public TopicExchange newInstance(UUID id, VirtualHost host, + AMQShortString name, + boolean durable, + int ticket, + boolean autoDelete) throws AMQException + { + TopicExchange exch = new TopicExchange(); + exch.initialise(id, host, name, durable, ticket, autoDelete); + return exch; + } + + public AMQShortString getDefaultExchangeName() + { + return ExchangeDefaults.TOPIC_EXCHANGE_NAME; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java deleted file mode 100644 index 7eb476b15a..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java +++ /dev/null @@ -1,913 +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.federation; - -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQStoreException; -import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.BridgeConfig; -import org.apache.qpid.server.configuration.BridgeConfigType; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.flow.FlowCreditManager_0_10; -import org.apache.qpid.server.flow.WindowCreditManager; -import org.apache.qpid.server.message.MessageMetaData_0_10; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.subscription.Subscription_0_10; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.server.txn.AutoCommitTransaction; -import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.DeliveryProperties; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageCreditUnit; -import org.apache.qpid.transport.MessageFlowMode; -import org.apache.qpid.transport.MessageReject; -import org.apache.qpid.transport.MessageRejectCode; -import org.apache.qpid.transport.MessageTransfer; -import org.apache.qpid.transport.Option; -import org.apache.qpid.transport.RangeSet; -import org.apache.qpid.transport.RangeSetFactory; -import org.apache.qpid.transport.Session; -import org.apache.qpid.transport.SessionException; -import org.apache.qpid.transport.SessionListener; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -public class Bridge implements BridgeConfig -{ - private static final String DURABLE = "durable"; - private static final String DYNAMIC = "dynamic"; - private static final String SRC_IS_QUEUE = "srcIsQueue"; - private static final String SRC_IS_LOCAL = "srcIsLocal"; - private static final String SOURCE = "source"; - private static final String DESTINATION = "destination"; - private static final String KEY = "key"; - private static final String TAG = "tag"; - private static final String EXCLUDES = "excludes"; - private final boolean _durable; - private final boolean _dynamic; - private final boolean _queueBridge; - private final boolean _localSource; - private final String _source; - private final String _destination; - private final String _key; - private final String _tag; - private final String _excludes; - private final BrokerLink _link; - private UUID _qmfId; - private long _createTime = System.currentTimeMillis(); - - private Session _session; - - private BridgeImpl _delegate; - - private final int _bridgeNo; - private AutoCommitTransaction _transaction; - - public Bridge(final BrokerLink brokerLink, - final int bridgeNo, - final boolean durable, - final boolean dynamic, - final boolean srcIsQueue, - final boolean srcIsLocal, - final String src, - final String dest, - final String key, - final String tag, - final String excludes) - { - _link = brokerLink; - _bridgeNo = bridgeNo; - _durable = durable; - _dynamic = dynamic; - _queueBridge = srcIsQueue; - _localSource = srcIsLocal; - _source = src; - _destination = dest; - _key = key; - _tag = tag; - _excludes = excludes; - _qmfId = durable ? brokerLink.getConfigStore().createPersistentId() : brokerLink.getConfigStore().createId(); - - _transaction = new AutoCommitTransaction(getVirtualHost().getMessageStore()); - - if(durable) - { - try - { - brokerLink.getVirtualHost().getMessageStore().createBridge(this); - } - catch (AMQStoreException e) - { - throw new RuntimeException(e); - } - } - - createDelegate(); - } - - private void createDelegate() - { - if(_dynamic) - { - if(_localSource) - { - // TODO - } - else - { - if(_queueBridge) - { - // TODO - } - else - { - _delegate = new DynamicExchangeBridge(); - } - } - } - else - { - if(_localSource) - { - if(_queueBridge) - { - _delegate = new StaticQueuePushBridge(); - } - else - { - _delegate = new StaticExchangePushBridge(); - } - } - else - { - if(_queueBridge) - { - _delegate = new StaticQueuePullBridge(); - } - else - { - _delegate = new StaticExchangePullBridge(); - } - } - } - } - - public Bridge(final BrokerLink brokerLink, - final int bridgeNo, - final UUID id, - final long createTime, - final Map arguments) - { - _link = brokerLink; - _bridgeNo = bridgeNo; - _qmfId = id; - brokerLink.getConfigStore().persistentIdInUse(id); - _createTime = createTime; - - _durable = Boolean.valueOf(arguments.get(DURABLE)); - _dynamic = Boolean.valueOf(arguments.get(DYNAMIC)); - _queueBridge = Boolean.valueOf(arguments.get(SRC_IS_QUEUE)); - _localSource = Boolean.valueOf(arguments.get(SRC_IS_LOCAL)); - _source = arguments.get(SOURCE); - _destination = arguments.get(DESTINATION); - _key = arguments.get(KEY); - _tag = arguments.get(TAG); - _excludes = arguments.get(EXCLUDES); - - //TODO. - _transaction = new AutoCommitTransaction(getVirtualHost().getMessageStore()); - - - if(_durable) - { - try - { - brokerLink.getVirtualHost().getMessageStore().createBridge(this); - } - catch (AMQStoreException e) - { - throw new RuntimeException(e); - } - } - - createDelegate(); - } - - - public Map getArguments() - { - Map arguments = new HashMap(); - - arguments.put(DURABLE, String.valueOf(_durable)); - arguments.put(DYNAMIC, String.valueOf(_dynamic)); - arguments.put(SRC_IS_QUEUE, String.valueOf(_queueBridge)); - arguments.put(SRC_IS_LOCAL, String.valueOf(_localSource)); - arguments.put(SOURCE, _source); - arguments.put(DESTINATION, _destination); - arguments.put(KEY, _key); - arguments.put(TAG, _tag); - arguments.put(EXCLUDES, _excludes); - - return Collections.unmodifiableMap(arguments); - } - - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public BridgeConfigType getConfigType() - { - return BridgeConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return getLink(); - } - - public boolean isDurable() - { - return _durable; - } - - public boolean isDynamic() - { - return _dynamic; - } - - public boolean isQueueBridge() - { - return _queueBridge; - } - - public boolean isLocalSource() - { - return _localSource; - } - - public String getSource() - { - return _source; - } - - public String getDestination() - { - return _destination; - } - - public String getKey() - { - return _key; - } - - public String getTag() - { - return _tag; - } - - public String getExcludes() - { - return _excludes; - } - - public BrokerLink getLink() - { - return _link; - } - - public Integer getChannelId() - { - return (_session == null) ? 0 : _session.getChannel(); - } - - public int getAckBatching() - { - return 0; - } - - public long getCreateTime() - { - return _createTime; - } - - @Override - public boolean equals(final Object o) - { - if (this == o) - { - return true; - } - if (o == null || getClass() != o.getClass()) - { - return false; - } - - final Bridge bridge = (Bridge) o; - - if (_durable != bridge._durable) - { - return false; - } - if (_dynamic != bridge._dynamic) - { - return false; - } - if (_localSource != bridge._localSource) - { - return false; - } - if (_queueBridge != bridge._queueBridge) - { - return false; - } - if (_destination != null ? !_destination.equals(bridge._destination) : bridge._destination != null) - { - return false; - } - if (_excludes != null ? !_excludes.equals(bridge._excludes) : bridge._excludes != null) - { - return false; - } - if (_key != null ? !_key.equals(bridge._key) : bridge._key != null) - { - return false; - } - if (_source != null ? !_source.equals(bridge._source) : bridge._source != null) - { - return false; - } - if (_tag != null ? !_tag.equals(bridge._tag) : bridge._tag != null) - { - return false; - } - - return true; - } - - @Override - public int hashCode() - { - int result = (_durable ? 1 : 0); - result = 31 * result + (_dynamic ? 1 : 0); - result = 31 * result + (_queueBridge ? 1 : 0); - result = 31 * result + (_localSource ? 1 : 0); - result = 31 * result + (_source != null ? _source.hashCode() : 0); - result = 31 * result + (_destination != null ? _destination.hashCode() : 0); - result = 31 * result + (_key != null ? _key.hashCode() : 0); - result = 31 * result + (_tag != null ? _tag.hashCode() : 0); - result = 31 * result + (_excludes != null ? _excludes.hashCode() : 0); - return result; - } - - public void setSession(final Session session) - { - _session = session; - _delegate.setSession(session); - } - - private long getMessageWindowSize() - { - return 10l; - } - - - VirtualHost getVirtualHost() - { - return _link.getVirtualHost(); - } - - public void close() - { - // TODO - _delegate.close(); - _session = null; - } - - - - private interface BridgeImpl - { - void setSession(Session session); - - void close(); - } - - private abstract class AbstractPullBridge implements BridgeImpl, SessionListener - { - public final void setSession(final Session session) - { - session.setSessionListener(this); - onSession(); - - } - - abstract void onSession(); - - - - public void message(final Session ssn, final MessageTransfer xfr) - { - ExchangeRegistry exchangeRegistry = getVirtualHost().getExchangeRegistry(); - - Exchange exchange = exchangeRegistry.getExchange(_destination); - - // TODO - deal with exchange not existing - - DeliveryProperties delvProps = null; - if(xfr.getHeader() != null && (delvProps = xfr.getHeader().getDeliveryProperties()) != null && delvProps.hasTtl() && - !delvProps.hasExpiration()) - { - delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl()); - } - - MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr); - final MessageStore store = getVirtualHost().getMessageStore(); - StoredMessage storeMessage = store.addMessage(messageMetaData); - storeMessage.addContent(0,xfr.getBody()); - storeMessage.flushToStore(); - MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)_session).getReference()); - - List queues = exchange.route(message); - - - - if(queues != null && queues.size() != 0) - { - enqueue(message, queues); - } - else - { - if(delvProps == null || !delvProps.hasDiscardUnroutable() || !delvProps.getDiscardUnroutable()) - { - if(xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT) - { - RangeSet rejects = RangeSetFactory.createRangeSet(); - rejects.add(xfr.getId()); - MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable"); - ssn.invoke(reject); - } - else - { - Exchange alternate = exchange.getAlternateExchange(); - if(alternate != null) - { - queues = alternate.route(message); - if(queues != null && queues.size() != 0) - { - enqueue(message, queues); - } - else - { - //TODO - log the message discard - } - } - else - { - //TODO - log the message discard - } - - - } - } - - - } - - ssn.processed(xfr); - - } - - - private void enqueue(final ServerMessage message, final List queues) - { - _transaction.enqueue(queues,message, new ServerTransaction.Action() - { - - private BaseQueue[] _queues = queues.toArray(new BaseQueue[queues.size()]); - - public void postCommit() - { - for(int i = 0; i < _queues.length; i++) - { - try - { - _queues[i].enqueue(message); - } - catch (AMQException e) - { - // TODO - - throw new RuntimeException(e); - } - } - } - - public void onRollback() - { - // NO-OP - } - }, 0L); - } - - public void exception(final Session session, final SessionException exception) - { - // TODO - Handle exceptions - } - - public void closed(final Session session) - { - // TODO - handle close - } - - public void opened(final Session session) - { - // this method never called - } - - public void resumed(final Session session) - { - // will never resume these sessions - } - - - - } - - private final class StaticExchangePullBridge extends AbstractPullBridge - { - private final String _tmpQueueName = "bridge_queue_" + _bridgeNo + "_" + _link.getFederationTag();; - - public void onSession() - { - - final HashMap options = new HashMap(); - options.put("qpid.trace.exclude", _link.getFederationTag()); - options.put("qpid.trace.id",_link.getRemoteFederationTag()); - _session.queueDeclare(_tmpQueueName,null, options, Option.AUTO_DELETE, Option.EXCLUSIVE); - _session.sync(); - // todo check exception - final Map bindingArgs = new HashMap(); - _session.exchangeBind(_tmpQueueName, _source, _key, bindingArgs); - _session.sync(); - // todo check exception - - final Map subscribeOptions = Collections.EMPTY_MAP; - final String subName = String.valueOf(_bridgeNo); - _session.messageSubscribe(_tmpQueueName, - subName,MessageAcceptMode.NONE,MessageAcquireMode.PRE_ACQUIRED,null,0l, subscribeOptions); - _session.sync(); - // todo check exception - - _session.messageSetFlowMode(subName,MessageFlowMode.WINDOW); - _session.messageFlow(subName, MessageCreditUnit.MESSAGE, getMessageWindowSize()); - _session.messageFlow(subName, MessageCreditUnit.BYTE, 0xFFFFFFFF); - - } - - public void close() - { - // TODO - } - } - - private final class StaticQueuePullBridge extends AbstractPullBridge - { - - public void onSession() - { - - final Map subscribeOptions = Collections.EMPTY_MAP; - final String subName = String.valueOf(_bridgeNo); - _session.messageSubscribe(_source, - subName,MessageAcceptMode.NONE,MessageAcquireMode.PRE_ACQUIRED,null,0l, subscribeOptions); - _session.sync(); - // todo check exception - - _session.messageSetFlowMode(subName,MessageFlowMode.WINDOW); - _session.messageFlow(subName, MessageCreditUnit.MESSAGE, getMessageWindowSize()); - _session.messageFlow(subName, MessageCreditUnit.BYTE, 0xFFFFFFFF); - - } - - public void close() - { - // TODO - } - } - - private final class DynamicExchangeBridge extends AbstractPullBridge implements Exchange.BindingListener - { - private final String _tmpQueueName = "bridge_queue_" + _bridgeNo + "_" + _link.getFederationTag(); - - private final ConcurrentMap _bindings = new ConcurrentHashMap(); - - - void onSession() - { - - - final HashMap options = new HashMap(); - options.put("qpid.trace.exclude", _link.getFederationTag()); - options.put("qpid.trace.id",_link.getRemoteFederationTag()); - _session.queueDeclare(_tmpQueueName,null, options, Option.AUTO_DELETE, Option.EXCLUSIVE); - _session.sync(); - // todo - check exception - - final Map subscribeOptions = Collections.EMPTY_MAP; - final String subName = String.valueOf(_bridgeNo); - _session.messageSubscribe(_tmpQueueName, - subName,MessageAcceptMode.NONE,MessageAcquireMode.PRE_ACQUIRED,null,0l, subscribeOptions); - _session.sync(); - // todo check exception - _session.messageSetFlowMode(subName,MessageFlowMode.WINDOW); - _session.messageFlow(subName, MessageCreditUnit.MESSAGE, getMessageWindowSize()); - _session.messageFlow(subName, MessageCreditUnit.BYTE, 0xFFFFFFFF); - _session.sync(); - // todo check exception - - - ExchangeRegistry exchangeRegistry = getVirtualHost().getExchangeRegistry(); - - Exchange exchange = exchangeRegistry.getExchange(_destination); - - // TODO - check null - - exchange.addBindingListener(this); - - Collection bindings = exchange.getBindings(); - for(Binding binding : bindings) - { - propogateBinding(binding); - } - - } - - private void propogateBinding(final Binding binding) - { - if(_bindings.putIfAbsent(binding,binding)== null) - { - Map arguments = new HashMap(binding.getArguments()); - - if(arguments.get("qpid.fed.origin") == null) - { - arguments.put("qpid.fed.op",""); - arguments.put("qpid.fed.origin",_link.getFederationTag()); - arguments.put("qpid.fed.tags",_link.getFederationTag()); - } - else - { - String tags = (String) arguments.get("qpid.fed.tags"); - if(tags == null) - { - tags = _link.getFederationTag(); - } - else - { - if(Arrays.asList(tags.split(",")).contains(_link.getFederationTag())) - { - return; - } - tags += "," + _link.getFederationTag(); - } - arguments.put("qpid.fed.tags", tags); - } - - _session.exchangeBind(_tmpQueueName, _source, binding.getBindingKey(), arguments); - _session.sync(); - // TODO - check exception? - - } - } - - private void propogateBindingRemoval(final Binding binding) - { - if(_bindings.remove(binding) != null) - { - // TODO - this is wrong!!!! - _session.exchangeUnbind(_tmpQueueName, _source, binding.getBindingKey()); - } - } - - - public void bindingAdded(final Exchange exchange, final Binding binding) - { - propogateBinding(binding); - } - - public void bindingRemoved(final Exchange exchange, final Binding binding) - { - propogateBindingRemoval(binding); - } - - public void close() - { - // TODO - } - } - - private class StaticExchangePushBridge implements BridgeImpl, SessionListener - { - private final String _tmpQueueName = "bridge_queue_" + _bridgeNo + "_" + _link.getFederationTag(); - private AMQQueue _queue; - - public void setSession(final Session session) - { - assert session instanceof ServerSession; - - session.setSessionListener(this); - - ExchangeRegistry exchangeRegistry = getVirtualHost().getExchangeRegistry(); - - Exchange exchange = exchangeRegistry.getExchange(_source); - - // TODO - Check null - - final HashMap options = new HashMap(); - options.put("qpid.trace.exclude", _link.getFederationTag()); - options.put("qpid.trace.id",_link.getRemoteFederationTag()); - - try - { - _queue = AMQQueueFactory.createAMQQueueImpl(null, - _tmpQueueName, - isDurable(), - _link.getFederationTag(), - false, - false, - getVirtualHost(), options); - } - catch (AMQException e) - { - // TODO - throw new RuntimeException(e); - } - - FlowCreditManager_0_10 creditManager = new WindowCreditManager(0xFFFFFFFF,getMessageWindowSize()); - - //TODO Handle the passing of non-null Filters and Arguments here - - Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session, - _destination, - MessageAcceptMode.NONE, - MessageAcquireMode.PRE_ACQUIRED, - MessageFlowMode.WINDOW, - creditManager, null,null); - - ((ServerSession)session).register(_destination, sub); - - try - { - _queue.registerSubscription(sub, true); - getVirtualHost().getBindingFactory().addBinding(_key, _queue, exchange, Collections.emptyMap()); - } - catch (AMQException e) - { - // TODO - throw new RuntimeException(e); - } - } - - public void close() - { - // TODO - } - - public void opened(final Session session) - { - // this method never called - } - - public void resumed(final Session session) - { - // this session will never be resumed - } - - public void message(final Session ssn, final MessageTransfer xfr) - { - // messages should not be sent ... should probably log error - } - - public void exception(final Session session, final SessionException exception) - { - // TODO - } - - public void closed(final Session session) - { - // TODO - } - } - - private class StaticQueuePushBridge implements BridgeImpl, SessionListener - { - private AMQQueue _queue; - - public void setSession(final Session session) - { - assert session instanceof ServerSession; - - session.setSessionListener(this); - - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - - _queue = queueRegistry.getQueue(_source); - - // TODO - null check - - FlowCreditManager_0_10 creditManager = new WindowCreditManager(0xFFFFFFFF,getMessageWindowSize()); - - //TODO Handle the passing of non-null Filters and Arguments here - - Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session, - _destination, - MessageAcceptMode.NONE, - MessageAcquireMode.PRE_ACQUIRED, - MessageFlowMode.WINDOW, - creditManager, null,null); - - ((ServerSession)session).register(_destination, sub); - - try - { - _queue.registerSubscription(sub, false); - } - catch (AMQException e) - { - // TODO - throw new RuntimeException(e); - } - - } - - public void close() - { - // TODO - } - - public void opened(final Session session) - { - // never called - } - - public void resumed(final Session session) - { - // session will not resume - } - - public void message(final Session ssn, final MessageTransfer xfr) - { - // should never be called ... should probably log error - } - - public void exception(final Session session, final SessionException exception) - { - // TODO - } - - public void closed(final Session session) - { - // TODO - } - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java b/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java deleted file mode 100644 index 1ef57c53cb..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java +++ /dev/null @@ -1,692 +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.federation; - -import org.apache.qpid.AMQStoreException; -import org.apache.qpid.common.ServerPropertyNames; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.ConnectionConfig; -import org.apache.qpid.server.configuration.ConnectionConfigType; -import org.apache.qpid.server.configuration.LinkConfig; -import org.apache.qpid.server.configuration.LinkConfigType; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.Binary; -import org.apache.qpid.transport.ClientDelegate; -import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.ConnectionException; -import org.apache.qpid.transport.ConnectionListener; -import org.apache.qpid.transport.ConnectionSettings; -import org.apache.qpid.transport.Session; -import org.apache.qpid.transport.SessionDelegate; -import org.apache.qpid.transport.TransportException; - -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.sasl.Sasl; -import javax.security.sasl.SaslClient; -import javax.security.sasl.SaslException; -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -public class BrokerLink implements LinkConfig, ConnectionListener -{ - - private static final int CORE_POOL_SIZE = 4; - - private static final ScheduledThreadPoolExecutor _threadPool = - new ScheduledThreadPoolExecutor(CORE_POOL_SIZE); - private static final String TRANSPORT = "transport"; - private static final String HOST = "host"; - private static final String PORT = "port"; - private static final String REMOTE_VHOST = "remoteVhost"; - private static final String DURABLE = "durable"; - private static final String AUTH_MECHANISM = "authMechanism"; - private static final String USERNAME = "username"; - private static final String PASSWORD = "password"; - - - private final String _transport; - private final String _host; - private final int _port; - private final String _remoteVhost; - private final boolean _durable; - private final String _authMechanism; - private final String _username; - private final String _password; - private final VirtualHost _virtualHost; - private UUID _qmfId; - private AtomicBoolean _closing = new AtomicBoolean(); - private final long _createTime; - private Connection _qpidConnection; - private AtomicReference _executor = new AtomicReference(); - private AtomicInteger _bridgeId = new AtomicInteger(); - - private final ConcurrentHashMap _bridges = new ConcurrentHashMap(); - private final ConcurrentHashMap _activeBridges = new ConcurrentHashMap(); - private final ConcurrentLinkedQueue _pendingBridges = new ConcurrentLinkedQueue(); - private String _remoteFederationTag; - - private ConnectionConfig _connectionConfig; - private ConnectionException _exception; - private String _lastErrorMessage; - private int _retryDelay = 1; - private final Runnable _makeConnectionTask = new Runnable() - { - public void run() - { - doMakeConnection(); - } - }; - - - - - public static enum State - { - OPERATIONAL, - DOWN, - ESTABLISHING, - DELETED - } - - - private volatile State _state = State.DOWN; - - private static final AtomicReferenceFieldUpdater _stateUpdater = - AtomicReferenceFieldUpdater.newUpdater(BrokerLink.class, State.class, "_state"); - - private class ConnectionConfigAdapter implements ConnectionConfig - { - private long _adapterCreateTime = System.currentTimeMillis(); - private UUID _qmfId = BrokerLink.this.getConfigStore().createId(); - - public VirtualHost getVirtualHost() - { - return BrokerLink.this.getVirtualHost(); - } - - public String getAddress() - { - return _host+":"+_port; - } - - public Boolean isIncoming() - { - return false; - } - - public Boolean isSystemConnection() - { - return true; - } - - public Boolean isFederationLink() - { - return true; - } - - public String getAuthId() - { - return _username; - } - - public String getRemoteProcessName() - { - return null; - } - - public Integer getRemotePID() - { - return null; - } - - public Integer getRemoteParentPID() - { - return null; - } - - public ConfigStore getConfigStore() - { - return getVirtualHost().getConfigStore(); - } - - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public ConnectionConfigType getConfigType() - { - return ConnectionConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return getVirtualHost(); - } - - public boolean isDurable() - { - return false; - } - - public long getCreateTime() - { - return _adapterCreateTime; - } - - public Boolean isShadow() - { - return false; - } - - public void mgmtClose() - { - _connectionConfig.mgmtClose(); - } - } - - private class SessionFactory implements Connection.SessionFactory - { - - public Session newSession(final Connection conn, final Binary name, final long expiry) - { - return new ServerSession(conn, new SessionDelegate(), name, expiry, _connectionConfig); - } - }; - - public BrokerLink(final VirtualHost virtualHost, UUID qmfId, long createTime, Map arguments) - { - _virtualHost = virtualHost; - _qmfId = qmfId; - virtualHost.getConfigStore().persistentIdInUse(qmfId); - _createTime = createTime; - _transport = arguments.get(TRANSPORT); - - _host = arguments.get(HOST); - _port = Integer.parseInt(arguments.get(PORT)); - _remoteVhost = arguments.get(REMOTE_VHOST); - _durable = Boolean.parseBoolean(arguments.get(DURABLE)); - _authMechanism = arguments.get("authMechanism"); - _username = arguments.get("username"); - _password = arguments.get("password"); - - if(_durable) - { - try - { - _virtualHost.getMessageStore().createBrokerLink(this); - } - catch (AMQStoreException e) - { - throw new RuntimeException(e); - } - } - - - _qpidConnection = new Connection(); - _connectionConfig = new ConnectionConfigAdapter(); - _qpidConnection.addConnectionListener(this); - - - makeConnection(); - - } - - - public BrokerLink(final VirtualHost virtualHost, - final String transport, - final String host, - final int port, - final String remoteVhost, - final boolean durable, - final String authMechanism, - final String username, - final String password) - { - _virtualHost = virtualHost; - _transport = transport; - _createTime = System.currentTimeMillis(); - _host = host; - _port = port; - _remoteVhost = remoteVhost; - _durable = durable; - _authMechanism = authMechanism; - _username = username; - _password = password; - _qmfId = durable ? virtualHost.getConfigStore().createPersistentId() : virtualHost.getConfigStore().createId(); - - if(durable) - { - try - { - _virtualHost.getMessageStore().createBrokerLink(this); - } - catch (AMQStoreException e) - { - throw new RuntimeException(e); - } - } - _qpidConnection = new Connection(); - _connectionConfig = new ConnectionConfigAdapter(); - _qpidConnection.addConnectionListener(this); - - makeConnection(); - } - - public Map getArguments() - { - Map arguments = new HashMap(); - - arguments.put(TRANSPORT, _transport); - arguments.put(HOST, _host); - arguments.put(PORT, String.valueOf(_port)); - arguments.put(REMOTE_VHOST, _remoteVhost); - arguments.put(DURABLE, String.valueOf(_durable)); - arguments.put(AUTH_MECHANISM, _authMechanism); - arguments.put(USERNAME, _username); - arguments.put(PASSWORD, _password); - - return Collections.unmodifiableMap(arguments); - } - - private final boolean updateState(State expected, State newState) - { - return _stateUpdater.compareAndSet(this,expected,newState); - } - - private void makeConnection() - { - _threadPool.execute(_makeConnectionTask); - } - - - - private void doMakeConnection() - { - if(updateState(State.DOWN, State.ESTABLISHING)) - { - try - { - _qpidConnection.setConnectionDelegate(new ClientDelegate(new ConnectionSettings()) - { - protected SaslClient createSaslClient(List brokerMechs) throws ConnectionException, - SaslException - { - Map saslProps = new HashMap(); - - - CallbackHandler cbh = new CallbackHandler() - { - public void handle(final Callback[] callbacks) - throws IOException, UnsupportedCallbackException - { - for (int i = 0; i < callbacks.length; i++) - { - Callback cb = callbacks[i]; - if (cb instanceof NameCallback) - { - ((NameCallback)cb).setName(_username); - } - else if (cb instanceof PasswordCallback) - { - ((PasswordCallback)cb).setPassword(_password.toCharArray()); - } - else - { - throw new UnsupportedCallbackException(cb); - } - } - - } - }; - final SaslClient sc = Sasl.createSaslClient(new String[] {"PLAIN"}, null, - getConnectionSettings().getSaslProtocol(), - getConnectionSettings().getSaslServerName(), - saslProps, cbh); - - return sc; - }}); - - _qpidConnection.connect(_host, _port, _remoteVhost, _username, _password, "ssl".equals(_transport), _authMechanism); - - final Map serverProps = _qpidConnection.getServerProperties(); - - _remoteFederationTag = (String) serverProps.get(ServerPropertyNames.FEDERATION_TAG); - if(_remoteFederationTag == null) - { - _remoteFederationTag = UUID.fromString(_transport+":"+_host+":"+_port).toString(); - } - _qpidConnection.setSessionFactory(new SessionFactory()); - - updateState(State.ESTABLISHING, State.OPERATIONAL); - - _retryDelay = 1; - - for(Bridge bridge : _bridges.values()) - { - if(_state != State.OPERATIONAL) - { - break; - } - addBridge(bridge); - } - - - } - catch (TransportException e) - { - _lastErrorMessage = e.getMessage(); - if(_retryDelay < 60) - { - _retryDelay <<= 1; - } - - updateState(State.ESTABLISHING, State.DOWN); - _activeBridges.clear(); - scheduleConnectionRetry(); - } - } - } - - private void scheduleConnectionRetry() - { - if(_state != State.DELETED) - { - _threadPool.schedule(_makeConnectionTask, _retryDelay, TimeUnit.SECONDS); - } - } - - public VirtualHost getVirtualHost() - { - return _virtualHost; - } - - public String getTransport() - { - return _transport; - } - - public String getHost() - { - return _host; - } - - public int getPort() - { - return _port; - } - - public String getRemoteVhost() - { - return _remoteVhost; - } - - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public LinkConfigType getConfigType() - { - return LinkConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return getVirtualHost(); - } - - public boolean isDurable() - { - return _durable; - } - - public String getAuthMechanism() - { - return _authMechanism; - } - - public String getUsername() - { - return _username; - } - - public String getPassword() - { - return _password; - } - - @Override - public boolean equals(final Object o) - { - if (this == o) - { - return true; - } - if (o == null || getClass() != o.getClass()) - { - return false; - } - - final BrokerLink that = (BrokerLink) o; - - if (_port != that._port) - { - return false; - } - if (_host != null ? !_host.equals(that._host) : that._host != null) - { - return false; - } - if (_remoteVhost != null ? !_remoteVhost.equals(that._remoteVhost) : that._remoteVhost != null) - { - return false; - } - if (_transport != null ? !_transport.equals(that._transport) : that._transport != null) - { - return false; - } - - return true; - } - - @Override - public int hashCode() - { - int result = _transport != null ? _transport.hashCode() : 0; - result = 31 * result + (_host != null ? _host.hashCode() : 0); - result = 31 * result + _port; - result = 31 * result + (_remoteVhost != null ? _remoteVhost.hashCode() : 0); - return result; - } - - public void close() - { - if(_closing.compareAndSet(false,true)) - { - // TODO - close connection - for(Bridge bridge : _bridges.values()) - { - bridge.close(); - } - _bridges.clear(); - - _virtualHost.removeBrokerConnection(this); - } - } - - public long getCreateTime() - { - return _createTime; - } - - public void createBridge(final boolean durable, - final boolean dynamic, - final boolean srcIsQueue, - final boolean srcIsLocal, - final String src, - final String dest, - final String key, - final String tag, - final String excludes) - { - if(!_closing.get()) - { - Bridge bridge = new Bridge(this, _bridgeId.incrementAndGet(), durable,dynamic,srcIsQueue,srcIsLocal,src,dest,key,tag,excludes); - if(_bridges.putIfAbsent(bridge, bridge) == null) - { - - addBridge(bridge); - } - } - - - } - - public void createBridge(final UUID id, final long createTime, final Map arguments) - { - if(!_closing.get()) - { - Bridge bridge = new Bridge(this, _bridgeId.incrementAndGet(), id, createTime, arguments); - if(_bridges.putIfAbsent(bridge, bridge) == null) - { - - addBridge(bridge); - } - } - } - - - private void addBridge(final Bridge bridge) - { - getConfigStore().addConfiguredObject(bridge); - - if(_state == State.OPERATIONAL && (_activeBridges.putIfAbsent(bridge,bridge) == null)) - { - - - Session session = _qpidConnection.createSession("Bridge(" - + (bridge.isDurable() ? "durable" : "transient") - + "," + (bridge.isDynamic() ? "dynamic" : "static") - + "," + (bridge.isQueueBridge() ? "queue" : "exchange") - + "," + (bridge.isLocalSource() ? "local-src" : "remote-src") - + ",[Source: '" + bridge.getSource() + "']" - + ",[Destination: '" + bridge.getDestination() + "']" - + ",[Key: '" + bridge.getKey() + "']" - + ",[Tag: '" + bridge.getTag() + "']" - + ".[Excludes: '" + bridge.getExcludes() + "'])"); - bridge.setSession(session); - - - if(_closing.get()) - { - bridge.close(); - } - } - - } - - public void opened(final Connection connection) - { - // this method not called - } - - public void exception(final Connection connection, final ConnectionException exception) - { - _exception = exception; - _lastErrorMessage = exception.getMessage(); - - } - - public void closed(final Connection connection) - { - State currentState = _state; - if(currentState != State.DOWN && currentState != State.DELETED && updateState(currentState, State.DOWN)) - { - scheduleConnectionRetry(); - } - } - - public ConfigStore getConfigStore() - { - return getVirtualHost().getConfigStore(); - } - - public String getFederationTag() - { - return getVirtualHost().getFederationTag(); - } - - public String getRemoteFederationTag() - { - return _remoteFederationTag; - } - - public String getState() - { - return _state.name(); - } - - public String getLastError() - { - return _lastErrorMessage; - } - - @Override - public String toString() - { - return "BrokerLink{" + - " _id=" + _qmfId + - ", _transport='" + _transport + '\'' + - ", _host='" + _host + '\'' + - ", _port=" + _port + - ", _remoteVhost='" + _remoteVhost + '\'' + - ", _durable=" + _durable + - ", _authMechanism='" + _authMechanism + '\'' + - ", _username='" + _username + '\'' + - ", _password='" + _password + '\'' + - ", _virtualHost=" + _virtualHost + - ", _createTime=" + _createTime + - ", _remoteFederationTag='" + _remoteFederationTag + '\'' + - ", _state=" + _state + - '}'; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java index b8c8411c5d..0339287e38 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java @@ -30,11 +30,11 @@ import org.apache.qpid.framing.ConnectionSecureOkBody; import org.apache.qpid.framing.ConnectionTuneBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import org.apache.qpid.server.state.AMQState; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; @@ -59,9 +59,10 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener public void methodReceived(AMQStateManager stateManager, ConnectionSecureOkBody body, int channelId) throws AMQException { + Broker broker = stateManager.getBroker(); AMQProtocolSession session = stateManager.getProtocolSession(); - AuthenticationManager authMgr = stateManager.getAuthenticationManager(); + SubjectCreator subjectCreator = stateManager.getSubjectCreator(); SaslServer ss = session.getSaslServer(); if (ss == null) @@ -69,7 +70,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener throw new AMQException("No SASL context set up in session"); } MethodRegistry methodRegistry = session.getMethodRegistry(); - AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse()); + SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse()); switch (authResult.getStatus()) { case ERROR: @@ -97,9 +98,9 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener stateManager.changeState(AMQState.CONNECTION_NOT_TUNED); ConnectionTuneBody tuneBody = - methodRegistry.createConnectionTuneBody(ApplicationRegistry.getInstance().getConfiguration().getMaxChannelCount(), - ConnectionStartOkMethodHandler.getConfiguredFrameSize(), - ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay()); + methodRegistry.createConnectionTuneBody((Integer)broker.getAttribute(Broker.SESSION_COUNT_LIMIT), + BrokerProperties.DEFAULT_FRAME_SIZE, + (Integer)broker.getAttribute(Broker.HEART_BEAT_DELAY)); session.writeFrame(tuneBody.generateFrame(0)); session.setAuthorizedSubject(authResult.getSubject()); disposeSaslServer(session); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java index a522b9f60f..e70fa6a37b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java @@ -29,12 +29,11 @@ import org.apache.qpid.framing.ConnectionStartOkBody; import org.apache.qpid.framing.ConnectionTuneBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import org.apache.qpid.server.state.AMQState; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; @@ -60,16 +59,17 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener< public void methodReceived(AMQStateManager stateManager, ConnectionStartOkBody body, int channelId) throws AMQException { + Broker broker = stateManager.getBroker(); AMQProtocolSession session = stateManager.getProtocolSession(); _logger.info("SASL Mechanism selected: " + body.getMechanism()); _logger.info("Locale selected: " + body.getLocale()); - AuthenticationManager authMgr = stateManager.getAuthenticationManager(); + SubjectCreator subjectCreator = stateManager.getSubjectCreator(); SaslServer ss = null; try { - ss = authMgr.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN(), session.getPeerPrincipal()); + ss = subjectCreator.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN(), session.getPeerPrincipal()); if (ss == null) { @@ -78,7 +78,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener< session.setSaslServer(ss); - final AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse()); + final SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse()); //save clientProperties session.setClientProperties(body.getClientProperties()); @@ -112,9 +112,9 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener< stateManager.changeState(AMQState.CONNECTION_NOT_TUNED); - ConnectionTuneBody tuneBody = methodRegistry.createConnectionTuneBody(ApplicationRegistry.getInstance().getConfiguration().getMaxChannelCount(), - getConfiguredFrameSize(), - ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay()); + ConnectionTuneBody tuneBody = methodRegistry.createConnectionTuneBody((Integer)broker.getAttribute(Broker.SESSION_COUNT_LIMIT), + BrokerProperties.DEFAULT_FRAME_SIZE, + (Integer)broker.getAttribute(Broker.HEART_BEAT_DELAY)); session.writeFrame(tuneBody.generateFrame(0)); break; case CONTINUE: @@ -148,13 +148,6 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener< } } - static int getConfiguredFrameSize() - { - final ServerConfiguration config = ApplicationRegistry.getInstance().getConfiguration(); - final int framesize = config.getFrameSize(); - _logger.info("Framesize set to " + framesize); - return framesize; - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java index 8756409f64..eed0cd6020 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java @@ -101,7 +101,7 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener emptyMap()); + _logger.info("Queue " + queueName + " bound to default exchange(" + defaultExchange.getNameShortString() + ")"); } } else if (queue.isExclusive() && !queue.isDurable() && (owningSession == null || owningSession.getConnectionModel() != protocolConnection)) diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/AbstractRootMessageLogger.java b/java/broker/src/main/java/org/apache/qpid/server/logging/AbstractRootMessageLogger.java index 545f2adea2..98da9074ef 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/AbstractRootMessageLogger.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/AbstractRootMessageLogger.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.logging; -import org.apache.qpid.server.configuration.ServerConfiguration; public abstract class AbstractRootMessageLogger implements RootMessageLogger { @@ -33,9 +32,9 @@ public abstract class AbstractRootMessageLogger implements RootMessageLogger } - public AbstractRootMessageLogger(ServerConfiguration config) + public AbstractRootMessageLogger(boolean statusUpdatesEnabled) { - _enabled = config.getStatusUpdatesEnabled(); + _enabled = statusUpdatesEnabled; } public boolean isEnabled() diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/Log4jMessageLogger.java b/java/broker/src/main/java/org/apache/qpid/server/logging/Log4jMessageLogger.java index ec506ab51c..b4e9f2f333 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/Log4jMessageLogger.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/Log4jMessageLogger.java @@ -20,23 +20,18 @@ */ package org.apache.qpid.server.logging; -import org.apache.log4j.Level; import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.ServerConfiguration; - public class Log4jMessageLogger extends AbstractRootMessageLogger { - public static final Level LEVEL = Level.toLevel("INFO"); - public Log4jMessageLogger() { super(); } - public Log4jMessageLogger(ServerConfiguration config) + public Log4jMessageLogger(boolean statusUpdatesEnabled) { - super(config); + super(statusUpdatesEnabled); } @Override @@ -51,7 +46,7 @@ public class Log4jMessageLogger extends AbstractRootMessageLogger if(isEnabled()) { Logger logger = Logger.getLogger(logHierarchy); - return logger.isEnabledFor(LEVEL); + return logger.isInfoEnabled(); } else { @@ -69,7 +64,6 @@ public class Log4jMessageLogger extends AbstractRootMessageLogger public void rawMessage(String message, Throwable throwable, String logHierarchy) { Logger logger = Logger.getLogger(logHierarchy); - - logger.log(LEVEL, message, throwable); + logger.info(message, throwable); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java b/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java index a1065319d3..d053dd3fe2 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java @@ -90,7 +90,6 @@ public class LogRecorder implements Appender, Iterable public LogRecorder() { - Logger.getRootLogger().addAppender(this); } @@ -109,7 +108,11 @@ public class LogRecorder implements Appender, Iterable @Override public void close() { - //TODO - Implement + } + + public void closeLogRecorder() + { + Logger.getRootLogger().removeAppender(this); } @Override diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AbstractManagementActor.java b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AbstractManagementActor.java new file mode 100644 index 0000000000..8cf121b3d9 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AbstractManagementActor.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.logging.actors; + +import java.security.AccessController; + +import javax.security.auth.Subject; + +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; + +public abstract class AbstractManagementActor extends AbstractActor +{ + /** + * Holds the principal name to display when principal subject is not available. + *

+ * This is useful for cases when users invoke JMX operation over JConsole + * attached to the local JVM. + */ + protected static final String UNKNOWN_PRINCIPAL = "N/A"; + + /** used when the principal name cannot be discovered from the Subject */ + private final String _fallbackPrincipalName; + + public AbstractManagementActor(RootMessageLogger rootLogger, String fallbackPrincipalName) + { + super(rootLogger); + _fallbackPrincipalName = fallbackPrincipalName; + } + + /** + * Returns current {@link AuthenticatedPrincipal} name or {@link #_fallbackPrincipalName} + * if it can't be found. + */ + protected String getPrincipalName() + { + String identity = _fallbackPrincipalName; + + final Subject subject = Subject.getSubject(AccessController.getContext()); + if (subject != null) + { + AuthenticatedPrincipal authenticatedPrincipal = AuthenticatedPrincipal.getOptionalAuthenticatedPrincipalFromSubject(subject); + if(authenticatedPrincipal != null) + { + identity = authenticatedPrincipal.getName(); + } + } + return identity; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java index 97134515a0..6251471139 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/CurrentActor.java @@ -105,6 +105,11 @@ public class CurrentActor { Stack stack = _currentActor.get(); stack.pop(); + + if (stack.isEmpty()) + { + _currentActor.remove(); + } } /** diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/HttpManagementActor.java b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/HttpManagementActor.java new file mode 100644 index 0000000000..9b445c2bd9 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/HttpManagementActor.java @@ -0,0 +1,62 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.logging.actors; + +import java.text.MessageFormat; + +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.subjects.LogSubjectFormat; + +/** + * HttpManagement actor to use in {@link AbstractServlet} to log all http management operational logging. + * + * An instance is required per http Session. + */ +public class HttpManagementActor extends AbstractManagementActor +{ + private String _cachedLogString; + private String _lastPrincipalName; + private String _address; + + public HttpManagementActor(RootMessageLogger rootLogger, String ip, int port) + { + super(rootLogger, UNKNOWN_PRINCIPAL); + _address = ip + ":" + port; + } + + private synchronized String getAndCacheLogString() + { + String principalName = getPrincipalName(); + + if(!principalName.equals(_lastPrincipalName)) + { + _lastPrincipalName = principalName; + _cachedLogString = "[" + MessageFormat.format(LogSubjectFormat.MANAGEMENT_FORMAT, principalName, _address) + "] "; + } + + return _cachedLogString; + } + + public String getLogMessage() + { + return getAndCacheLogString(); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java index a2f3506502..ba5ea47fc1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java @@ -21,58 +21,31 @@ package org.apache.qpid.server.logging.actors; import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.subjects.LogSubjectFormat; -import javax.management.remote.JMXPrincipal; -import javax.security.auth.Subject; -import java.security.AccessController; -import java.security.Principal; import java.text.MessageFormat; -import java.util.Set; /** * Management actor to use in {@link MBeanInvocationHandlerImpl} to log all management operational logging. */ -public class ManagementActor extends AbstractActor +public class ManagementActor extends AbstractManagementActor { - /** - * Holds the principal name to display when principal subject is not available. - *

- * This is useful for cases when users invoke JMX operation over JConsole - * attached to the local JVM. - */ - private static final String UNKNOWN_PRINCIPAL = "N/A"; - private String _lastThreadName = null; - /** - * LOG FORMAT for the ManagementActor, - * Uses a MessageFormat call to insert the required values according to - * these indices: - * - * 0 - User ID - * 1 - IP - */ - public static final String MANAGEMENT_FORMAT = "mng:{0}({1})"; - /** * The logString to be used for logging */ private String _logStringContainingPrincipal; - /** used when the principal name cannot be discovered from the Subject */ - private final String _fallbackPrincipalName; - /** @param rootLogger The RootLogger to use for this Actor */ public ManagementActor(RootMessageLogger rootLogger) { - super(rootLogger); - _fallbackPrincipalName = UNKNOWN_PRINCIPAL; + super(rootLogger, UNKNOWN_PRINCIPAL); } public ManagementActor(RootMessageLogger rootLogger, String principalName) { - super(rootLogger); - _fallbackPrincipalName = principalName; + super(rootLogger, principalName); } private synchronized String getAndCacheLogString() @@ -96,7 +69,7 @@ public class ManagementActor extends AbstractActor if (split.length == 2) { String ip = currentName.split("-")[1]; - actor = MessageFormat.format(MANAGEMENT_FORMAT, principalName, ip); + actor = MessageFormat.format(LogSubjectFormat.MANAGEMENT_FORMAT, principalName, ip); } else { @@ -119,33 +92,8 @@ public class ManagementActor extends AbstractActor return logString; } - /** - * Returns current JMX principal name. - * - * @return principal name or null if principal can not be found - */ - private String getPrincipalName() - { - String identity = _fallbackPrincipalName; - - // retrieve Subject from current AccessControlContext - final Subject subject = Subject.getSubject(AccessController.getContext()); - if (subject != null) - { - // retrieve JMXPrincipal from Subject - final Set principals = subject.getPrincipals(JMXPrincipal.class); - if (principals != null && !principals.isEmpty()) - { - final Principal principal = principals.iterator().next(); - identity = principal.getName(); - } - } - return identity; - } - public String getLogMessage() { return getAndCacheLogString(); } - } diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java deleted file mode 100644 index 931171b175..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java +++ /dev/null @@ -1,579 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.logging.log4j; - -import org.apache.log4j.Level; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; -import org.apache.log4j.xml.DOMConfigurator; -import org.apache.log4j.xml.Log4jEntityResolver; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.ErrorHandler; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -/** - * A facade over log4j that allows both the control of the runtime logging behaviour (that is, the ability to - * turn {@link Logger} on, off and control their {@link Level}, and the manipulation and reload - * of the log4j configuration file. - */ -public class LoggingFacade -{ - private static Logger LOGGER; - private static transient LoggingFacade _instance; - private final String _filename; - private final int _delay; - - public static LoggingFacade configure(String filename) throws LoggingFacadeException - { - _instance = new LoggingFacade(filename); - return _instance; - } - - public static LoggingFacade configureAndWatch(String filename, int delay) throws LoggingFacadeException - { - _instance = new LoggingFacade(filename, delay); - return _instance; - } - - public static LoggingFacade getCurrentInstance() - { - return _instance; - } - - private LoggingFacade(String filename) - { - DOMConfigurator.configure(filename); - - if(LOGGER == null) - { - LOGGER = Logger.getLogger(LoggingFacade.class); - } - _filename = filename; - _delay = 0; - } - - private LoggingFacade(String filename, int delay) - { - DOMConfigurator.configureAndWatch(filename, delay); - - if(LOGGER == null) - { - LOGGER = Logger.getLogger(LoggingFacade.class); - } - - _filename = filename; - _delay = delay; - } - - public int getLog4jLogWatchInterval() - { - return _delay; - } - - public synchronized void reload() throws LoggingFacadeException - { - DOMConfigurator.configure(_filename); - } - - /** The log4j XML configuration file DTD defines three possible element - * combinations for specifying optional logger+level settings. - * Must account for the following: - * - * OR - * OR - * - * - * Noting also that the level/priority child element is optional too, - * and not the only possible child element. - */ - public synchronized Map retrieveConfigFileLoggersLevels() throws LoggingFacadeException - { - try - { - Map loggerLevelList = new HashMap(); - LOGGER.info("Getting logger levels from log4j configuration file"); - - Document doc = parseConfigFile(_filename); - List categoryOrLoggerElements = buildListOfCategoryOrLoggerElements(doc); - - for (Element categoryOrLogger : categoryOrLoggerElements) - { - - Element priorityOrLevelElement; - try - { - priorityOrLevelElement = getPriorityOrLevelElement(categoryOrLogger); - } - catch (LoggingFacadeException lfe) - { - //there is no exiting priority or level to view, move onto next category/logger - continue; - } - - String categoryName = categoryOrLogger.getAttribute("name"); - String priorityOrLevelValue = priorityOrLevelElement.getAttribute("value"); - loggerLevelList.put(categoryName, priorityOrLevelValue); - } - - return loggerLevelList; - } - catch (IOException e) - { - throw new LoggingFacadeException(e); - } - } - - /** - * The log4j XML configuration file DTD defines 2 possible element - * combinations for specifying the optional root logger level settings - * Must account for the following: - * - * OR - * - * - * Noting also that the level/priority child element is optional too, - * and not the only possible child element. - */ - public synchronized String retrieveConfigFileRootLoggerLevel() throws LoggingFacadeException - { - try - { - Document doc = parseConfigFile(_filename); - - //retrieve the optional 'root' element node - NodeList rootElements = doc.getElementsByTagName("root"); - - if (rootElements.getLength() == 0) - { - //there is no root logger definition - return "N/A"; - } - - Element rootElement = (Element) rootElements.item(0); - Element levelElement = getPriorityOrLevelElement(rootElement); - - if(levelElement != null) - { - return levelElement.getAttribute("value"); - } - else - { - return "N/A"; - } - } - catch (IOException e) - { - throw new LoggingFacadeException(e); - } - } - - public synchronized void setConfigFileLoggerLevel(String logger, String level) throws LoggingFacadeException - { - LOGGER.info("Setting level to " + level + " for logger '" + logger - + "' in log4j xml configuration file: " + _filename); - - try - { - Document doc = parseConfigFile(_filename); - - List logElements = buildListOfCategoryOrLoggerElements(doc); - - //try to locate the specified logger/category in the elements retrieved - Element logElement = null; - for (Element e : logElements) - { - if (e.getAttribute("name").equals(logger)) - { - logElement = e; - break; - } - } - - if (logElement == null) - { - throw new LoggingFacadeException("Can't find logger " + logger); - } - - Element levelElement = getPriorityOrLevelElement(logElement); - - //update the element with the new level/priority - levelElement.setAttribute("value", level); - - //output the new file - writeUpdatedConfigFile(_filename, doc); - } - catch (IOException ioe) - { - throw new LoggingFacadeException(ioe); - } - catch (TransformerConfigurationException e) - { - throw new LoggingFacadeException(e); - } - } - - public synchronized void setConfigFileRootLoggerLevel(String level) throws LoggingFacadeException - { - try - { - LOGGER.info("Setting level to " + level + " for the Root logger in " + - "log4j xml configuration file: " + _filename); - - Document doc = parseConfigFile(_filename); - - //retrieve the optional 'root' element node - NodeList rootElements = doc.getElementsByTagName("root"); - - if (rootElements.getLength() == 0) - { - throw new LoggingFacadeException("Configuration contains no root element"); - } - - Element rootElement = (Element) rootElements.item(0); - Element levelElement = getPriorityOrLevelElement(rootElement); - - //update the element with the new level/priority - levelElement.setAttribute("value", level); - - //output the new file - writeUpdatedConfigFile(_filename, doc); - } - catch (IOException e) - { - throw new LoggingFacadeException(e); - } - catch (TransformerConfigurationException e) - { - throw new LoggingFacadeException(e); - } - } - - public List getAvailableLoggerLevels() - { - return new ArrayList() - {{ - add(Level.ALL.toString()); - add(Level.TRACE.toString()); - add(Level.DEBUG.toString()); - add(Level.INFO.toString()); - add(Level.WARN.toString()); - add(Level.ERROR.toString()); - add(Level.FATAL.toString()); - add(Level.OFF.toString()); - }}; - } - - public String retrieveRuntimeRootLoggerLevel() - { - Logger rootLogger = Logger.getRootLogger(); - return rootLogger.getLevel().toString(); - } - - public void setRuntimeRootLoggerLevel(String level) - { - Level newLevel = Level.toLevel(level); - - LOGGER.info("Setting RootLogger level to " + level); - - Logger log = Logger.getRootLogger(); - log.setLevel(newLevel); - } - - public void setRuntimeLoggerLevel(String loggerName, String level) throws LoggingFacadeException - { - Level newLevel = level == null ? null : Level.toLevel(level); - - Logger targetLogger = findRuntimeLogger(loggerName); - - if(targetLogger == null) - { - throw new LoggingFacadeException("Can't find logger " + loggerName); - } - - LOGGER.info("Setting level to " + newLevel + " for logger '" + targetLogger.getName() + "'"); - - targetLogger.setLevel(newLevel); - } - - public Map retrieveRuntimeLoggersLevels() - { - LOGGER.info("Getting levels for currently active log4j loggers"); - - Map levels = new HashMap(); - @SuppressWarnings("unchecked") - Enumeration loggers = LogManager.getCurrentLoggers(); - - while (loggers.hasMoreElements()) - { - Logger logger = loggers.nextElement(); - levels.put(logger.getName(), logger.getEffectiveLevel().toString()); - } - - return levels; - } - - private void writeUpdatedConfigFile(String log4jConfigFileName, Document doc) throws IOException, TransformerConfigurationException - { - File log4jConfigFile = new File(log4jConfigFileName); - - if (!log4jConfigFile.canWrite()) - { - LOGGER.warn("Specified log4j XML configuration file is not writable: " + log4jConfigFile); - throw new IOException("Specified log4j XML configuration file is not writable"); - } - - Transformer transformer = null; - transformer = TransformerFactory.newInstance().newTransformer(); - - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "log4j.dtd"); - DOMSource source = new DOMSource(doc); - - File tmp; - Random r = new Random(); - - do - { - tmp = new File(log4jConfigFile.getAbsolutePath() + r.nextInt() + ".tmp"); - } - while(tmp.exists()); - - tmp.deleteOnExit(); - - try - { - StreamResult result = new StreamResult(new FileOutputStream(tmp)); - transformer.transform(source, result); - } - catch (TransformerException e) - { - LOGGER.warn("Could not transform the XML into new file: ", e); - throw new IOException("Could not transform the XML into new file: ", e); - } - - // Swap temp file in to replace existing configuration file. - File old = new File(log4jConfigFile.getAbsoluteFile() + ".old"); - if (old.exists()) - { - old.delete(); - } - - if(!log4jConfigFile.renameTo(old)) - { - //unable to rename the existing file to the backup name - LOGGER.error("Could not backup the existing log4j XML file"); - throw new IOException("Could not backup the existing log4j XML file"); - } - - if(!tmp.renameTo(log4jConfigFile)) - { - //failed to rename the new file to the required filename - - if(!old.renameTo(log4jConfigFile)) - { - //unable to return the backup to required filename - LOGGER.error("Could not rename the new log4j configuration file into place, and unable to restore original file"); - throw new IOException("Could not rename the new log4j configuration file into place, and unable to restore original file"); - } - - LOGGER.error("Could not rename the new log4j configuration file into place"); - throw new IOException("Could not rename the new log4j configuration file into place"); - } - } - - //method to parse the XML configuration file, validating it in the process, and returning a DOM Document of the content. - private static Document parseConfigFile(String fileName) throws IOException - { - //check file was specified, exists, and is readable - if(fileName == null) - { - LOGGER.warn("Provided log4j XML configuration filename is null"); - throw new IOException("Provided log4j XML configuration filename is null"); - } - - File configFile = new File(fileName); - - if (!configFile.exists()) - { - LOGGER.warn("The log4j XML configuration file could not be found: " + fileName); - throw new IOException("The log4j XML configuration file could not be found"); - } - else if (!configFile.canRead()) - { - LOGGER.warn("The log4j XML configuration file is not readable: " + fileName); - throw new IOException("The log4j XML configuration file is not readable"); - } - - //parse it - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder; - Document doc; - - ErrorHandler errHandler = new QpidLog4JSaxErrorHandler(); - try - { - docFactory.setValidating(true); - docBuilder = docFactory.newDocumentBuilder(); - docBuilder.setErrorHandler(errHandler); - docBuilder.setEntityResolver(new Log4jEntityResolver()); - doc = docBuilder.parse(fileName); - } - catch (ParserConfigurationException e) - { - LOGGER.warn("Unable to parse the log4j XML file due to possible configuration error: ", e); - throw new IOException("Unable to parse the log4j XML file due to possible configuration error: ", e); - } - catch (SAXException e) - { - LOGGER.warn("The specified log4j XML file is invalid: ", e); - throw new IOException("The specified log4j XML file is invalid: ", e); - } - catch (IOException e) - { - LOGGER.warn("Unable to parse the specified log4j XML file", e); - throw new IOException("Unable to parse the specified log4j XML file: ", e); - } - - return doc; - } - - private Logger findRuntimeLogger(String loggerName) - { - Logger targetLogger = null; - @SuppressWarnings("unchecked") - Enumeration loggers = LogManager.getCurrentLoggers(); - while(loggers.hasMoreElements()) - { - targetLogger = loggers.nextElement(); - if (targetLogger.getName().equals(loggerName)) - { - return targetLogger; - } - } - return null; - } - - private List buildListOfCategoryOrLoggerElements(Document doc) - { - //retrieve the 'category' and 'logger' element nodes - NodeList categoryElements = doc.getElementsByTagName("category"); - NodeList loggerElements = doc.getElementsByTagName("logger"); - - //collect them into a single elements list - List logElements = new ArrayList(); - - for (int i = 0; i < categoryElements.getLength(); i++) - { - logElements.add((Element) categoryElements.item(i)); - } - for (int i = 0; i < loggerElements.getLength(); i++) - { - logElements.add((Element) loggerElements.item(i)); - } - return logElements; - } - - private Element getPriorityOrLevelElement(Element categoryOrLogger) throws LoggingFacadeException - { - //retrieve the optional 'priority' or 'level' sub-element value. - //It may not be the only child node, so request by tag name. - NodeList priorityElements = categoryOrLogger.getElementsByTagName("priority"); - NodeList levelElements = categoryOrLogger.getElementsByTagName("level"); - - Element levelElement = null; - if (priorityElements.getLength() != 0) - { - levelElement = (Element) priorityElements.item(0); - } - else if (levelElements.getLength() != 0) - { - levelElement = (Element) levelElements.item(0); - } - else - { - throw new LoggingFacadeException("Configuration " + categoryOrLogger.getNodeName() - + " element contains neither priority nor level child"); - } - return levelElement; - } - - private static class QpidLog4JSaxErrorHandler implements ErrorHandler - { - public void error(SAXParseException e) throws SAXException - { - if(LOGGER != null) - { - LOGGER.warn(constructMessage("Error parsing XML file", e)); - } - else - { - System.err.println(constructMessage("Error parsing XML file", e)); - } - } - - public void fatalError(SAXParseException e) throws SAXException - { - throw new SAXException(constructMessage("Fatal error parsing XML file", e)); - } - - public void warning(SAXParseException e) throws SAXException - { - if(LOGGER != null) - { - LOGGER.warn(constructMessage("Warning parsing XML file", e)); - } - else - { - System.err.println(constructMessage("Warning parsing XML file", e)); - } - } - - private static String constructMessage(final String msg, final SAXParseException ex) - { - return msg + ": Line " + ex.getLineNumber()+" column " +ex.getColumnNumber() + ": " + ex.getMessage(); - } - } -} - diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingManagementFacade.java b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingManagementFacade.java new file mode 100644 index 0000000000..6a961c8fa4 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingManagementFacade.java @@ -0,0 +1,579 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.logging.log4j; + +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.apache.log4j.xml.DOMConfigurator; +import org.apache.log4j.xml.Log4jEntityResolver; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +/** + * A facade over log4j that allows both the control of the runtime logging behaviour (that is, the ability to + * turn {@link Logger} on, off and control their {@link Level}, and the manipulation and reload + * of the log4j configuration file. + */ +public class LoggingManagementFacade +{ + private static Logger LOGGER; + private static transient LoggingManagementFacade _instance; + private final String _filename; + private final int _delay; + + public static LoggingManagementFacade configure(String filename) throws LoggingFacadeException + { + _instance = new LoggingManagementFacade(filename); + return _instance; + } + + public static LoggingManagementFacade configureAndWatch(String filename, int delay) throws LoggingFacadeException + { + _instance = new LoggingManagementFacade(filename, delay); + return _instance; + } + + public static LoggingManagementFacade getCurrentInstance() + { + return _instance; + } + + private LoggingManagementFacade(String filename) + { + DOMConfigurator.configure(filename); + + if(LOGGER == null) + { + LOGGER = Logger.getLogger(LoggingManagementFacade.class); + } + _filename = filename; + _delay = 0; + } + + private LoggingManagementFacade(String filename, int delay) + { + DOMConfigurator.configureAndWatch(filename, delay); + + if(LOGGER == null) + { + LOGGER = Logger.getLogger(LoggingManagementFacade.class); + } + + _filename = filename; + _delay = delay; + } + + public int getLog4jLogWatchInterval() + { + return _delay; + } + + public synchronized void reload() throws LoggingFacadeException + { + DOMConfigurator.configure(_filename); + } + + /** The log4j XML configuration file DTD defines three possible element + * combinations for specifying optional logger+level settings. + * Must account for the following: + * + * OR + * OR + * + * + * Noting also that the level/priority child element is optional too, + * and not the only possible child element. + */ + public synchronized Map retrieveConfigFileLoggersLevels() throws LoggingFacadeException + { + try + { + Map loggerLevelList = new HashMap(); + LOGGER.info("Getting logger levels from log4j configuration file"); + + Document doc = parseConfigFile(_filename); + List categoryOrLoggerElements = buildListOfCategoryOrLoggerElements(doc); + + for (Element categoryOrLogger : categoryOrLoggerElements) + { + + Element priorityOrLevelElement; + try + { + priorityOrLevelElement = getPriorityOrLevelElement(categoryOrLogger); + } + catch (LoggingFacadeException lfe) + { + //there is no exiting priority or level to view, move onto next category/logger + continue; + } + + String categoryName = categoryOrLogger.getAttribute("name"); + String priorityOrLevelValue = priorityOrLevelElement.getAttribute("value"); + loggerLevelList.put(categoryName, priorityOrLevelValue); + } + + return loggerLevelList; + } + catch (IOException e) + { + throw new LoggingFacadeException(e); + } + } + + /** + * The log4j XML configuration file DTD defines 2 possible element + * combinations for specifying the optional root logger level settings + * Must account for the following: + * + * OR + * + * + * Noting also that the level/priority child element is optional too, + * and not the only possible child element. + */ + public synchronized String retrieveConfigFileRootLoggerLevel() throws LoggingFacadeException + { + try + { + Document doc = parseConfigFile(_filename); + + //retrieve the optional 'root' element node + NodeList rootElements = doc.getElementsByTagName("root"); + + if (rootElements.getLength() == 0) + { + //there is no root logger definition + return "N/A"; + } + + Element rootElement = (Element) rootElements.item(0); + Element levelElement = getPriorityOrLevelElement(rootElement); + + if(levelElement != null) + { + return levelElement.getAttribute("value"); + } + else + { + return "N/A"; + } + } + catch (IOException e) + { + throw new LoggingFacadeException(e); + } + } + + public synchronized void setConfigFileLoggerLevel(String logger, String level) throws LoggingFacadeException + { + LOGGER.info("Setting level to " + level + " for logger '" + logger + + "' in log4j xml configuration file: " + _filename); + + try + { + Document doc = parseConfigFile(_filename); + + List logElements = buildListOfCategoryOrLoggerElements(doc); + + //try to locate the specified logger/category in the elements retrieved + Element logElement = null; + for (Element e : logElements) + { + if (e.getAttribute("name").equals(logger)) + { + logElement = e; + break; + } + } + + if (logElement == null) + { + throw new LoggingFacadeException("Can't find logger " + logger); + } + + Element levelElement = getPriorityOrLevelElement(logElement); + + //update the element with the new level/priority + levelElement.setAttribute("value", level); + + //output the new file + writeUpdatedConfigFile(_filename, doc); + } + catch (IOException ioe) + { + throw new LoggingFacadeException(ioe); + } + catch (TransformerConfigurationException e) + { + throw new LoggingFacadeException(e); + } + } + + public synchronized void setConfigFileRootLoggerLevel(String level) throws LoggingFacadeException + { + try + { + LOGGER.info("Setting level to " + level + " for the Root logger in " + + "log4j xml configuration file: " + _filename); + + Document doc = parseConfigFile(_filename); + + //retrieve the optional 'root' element node + NodeList rootElements = doc.getElementsByTagName("root"); + + if (rootElements.getLength() == 0) + { + throw new LoggingFacadeException("Configuration contains no root element"); + } + + Element rootElement = (Element) rootElements.item(0); + Element levelElement = getPriorityOrLevelElement(rootElement); + + //update the element with the new level/priority + levelElement.setAttribute("value", level); + + //output the new file + writeUpdatedConfigFile(_filename, doc); + } + catch (IOException e) + { + throw new LoggingFacadeException(e); + } + catch (TransformerConfigurationException e) + { + throw new LoggingFacadeException(e); + } + } + + public List getAvailableLoggerLevels() + { + return new ArrayList() + {{ + add(Level.ALL.toString()); + add(Level.TRACE.toString()); + add(Level.DEBUG.toString()); + add(Level.INFO.toString()); + add(Level.WARN.toString()); + add(Level.ERROR.toString()); + add(Level.FATAL.toString()); + add(Level.OFF.toString()); + }}; + } + + public String retrieveRuntimeRootLoggerLevel() + { + Logger rootLogger = Logger.getRootLogger(); + return rootLogger.getLevel().toString(); + } + + public void setRuntimeRootLoggerLevel(String level) + { + Level newLevel = Level.toLevel(level); + + LOGGER.info("Setting RootLogger level to " + level); + + Logger log = Logger.getRootLogger(); + log.setLevel(newLevel); + } + + public void setRuntimeLoggerLevel(String loggerName, String level) throws LoggingFacadeException + { + Level newLevel = level == null ? null : Level.toLevel(level); + + Logger targetLogger = findRuntimeLogger(loggerName); + + if(targetLogger == null) + { + throw new LoggingFacadeException("Can't find logger " + loggerName); + } + + LOGGER.info("Setting level to " + newLevel + " for logger '" + targetLogger.getName() + "'"); + + targetLogger.setLevel(newLevel); + } + + public Map retrieveRuntimeLoggersLevels() + { + LOGGER.info("Getting levels for currently active log4j loggers"); + + Map levels = new HashMap(); + @SuppressWarnings("unchecked") + Enumeration loggers = LogManager.getCurrentLoggers(); + + while (loggers.hasMoreElements()) + { + Logger logger = loggers.nextElement(); + levels.put(logger.getName(), logger.getEffectiveLevel().toString()); + } + + return levels; + } + + private void writeUpdatedConfigFile(String log4jConfigFileName, Document doc) throws IOException, TransformerConfigurationException + { + File log4jConfigFile = new File(log4jConfigFileName); + + if (!log4jConfigFile.canWrite()) + { + LOGGER.warn("Specified log4j XML configuration file is not writable: " + log4jConfigFile); + throw new IOException("Specified log4j XML configuration file is not writable"); + } + + Transformer transformer = null; + transformer = TransformerFactory.newInstance().newTransformer(); + + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "log4j.dtd"); + DOMSource source = new DOMSource(doc); + + File tmp; + Random r = new Random(); + + do + { + tmp = new File(log4jConfigFile.getAbsolutePath() + r.nextInt() + ".tmp"); + } + while(tmp.exists()); + + tmp.deleteOnExit(); + + try + { + StreamResult result = new StreamResult(new FileOutputStream(tmp)); + transformer.transform(source, result); + } + catch (TransformerException e) + { + LOGGER.warn("Could not transform the XML into new file: ", e); + throw new IOException("Could not transform the XML into new file: ", e); + } + + // Swap temp file in to replace existing configuration file. + File old = new File(log4jConfigFile.getAbsoluteFile() + ".old"); + if (old.exists()) + { + old.delete(); + } + + if(!log4jConfigFile.renameTo(old)) + { + //unable to rename the existing file to the backup name + LOGGER.error("Could not backup the existing log4j XML file"); + throw new IOException("Could not backup the existing log4j XML file"); + } + + if(!tmp.renameTo(log4jConfigFile)) + { + //failed to rename the new file to the required filename + + if(!old.renameTo(log4jConfigFile)) + { + //unable to return the backup to required filename + LOGGER.error("Could not rename the new log4j configuration file into place, and unable to restore original file"); + throw new IOException("Could not rename the new log4j configuration file into place, and unable to restore original file"); + } + + LOGGER.error("Could not rename the new log4j configuration file into place"); + throw new IOException("Could not rename the new log4j configuration file into place"); + } + } + + //method to parse the XML configuration file, validating it in the process, and returning a DOM Document of the content. + private static Document parseConfigFile(String fileName) throws IOException + { + //check file was specified, exists, and is readable + if(fileName == null) + { + LOGGER.warn("Provided log4j XML configuration filename is null"); + throw new IOException("Provided log4j XML configuration filename is null"); + } + + File configFile = new File(fileName); + + if (!configFile.exists()) + { + LOGGER.warn("The log4j XML configuration file could not be found: " + fileName); + throw new IOException("The log4j XML configuration file could not be found"); + } + else if (!configFile.canRead()) + { + LOGGER.warn("The log4j XML configuration file is not readable: " + fileName); + throw new IOException("The log4j XML configuration file is not readable"); + } + + //parse it + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder; + Document doc; + + ErrorHandler errHandler = new QpidLog4JSaxErrorHandler(); + try + { + docFactory.setValidating(true); + docBuilder = docFactory.newDocumentBuilder(); + docBuilder.setErrorHandler(errHandler); + docBuilder.setEntityResolver(new Log4jEntityResolver()); + doc = docBuilder.parse(fileName); + } + catch (ParserConfigurationException e) + { + LOGGER.warn("Unable to parse the log4j XML file due to possible configuration error: ", e); + throw new IOException("Unable to parse the log4j XML file due to possible configuration error: ", e); + } + catch (SAXException e) + { + LOGGER.warn("The specified log4j XML file is invalid: ", e); + throw new IOException("The specified log4j XML file is invalid: ", e); + } + catch (IOException e) + { + LOGGER.warn("Unable to parse the specified log4j XML file", e); + throw new IOException("Unable to parse the specified log4j XML file: ", e); + } + + return doc; + } + + private Logger findRuntimeLogger(String loggerName) + { + Logger targetLogger = null; + @SuppressWarnings("unchecked") + Enumeration loggers = LogManager.getCurrentLoggers(); + while(loggers.hasMoreElements()) + { + targetLogger = loggers.nextElement(); + if (targetLogger.getName().equals(loggerName)) + { + return targetLogger; + } + } + return null; + } + + private List buildListOfCategoryOrLoggerElements(Document doc) + { + //retrieve the 'category' and 'logger' element nodes + NodeList categoryElements = doc.getElementsByTagName("category"); + NodeList loggerElements = doc.getElementsByTagName("logger"); + + //collect them into a single elements list + List logElements = new ArrayList(); + + for (int i = 0; i < categoryElements.getLength(); i++) + { + logElements.add((Element) categoryElements.item(i)); + } + for (int i = 0; i < loggerElements.getLength(); i++) + { + logElements.add((Element) loggerElements.item(i)); + } + return logElements; + } + + private Element getPriorityOrLevelElement(Element categoryOrLogger) throws LoggingFacadeException + { + //retrieve the optional 'priority' or 'level' sub-element value. + //It may not be the only child node, so request by tag name. + NodeList priorityElements = categoryOrLogger.getElementsByTagName("priority"); + NodeList levelElements = categoryOrLogger.getElementsByTagName("level"); + + Element levelElement = null; + if (priorityElements.getLength() != 0) + { + levelElement = (Element) priorityElements.item(0); + } + else if (levelElements.getLength() != 0) + { + levelElement = (Element) levelElements.item(0); + } + else + { + throw new LoggingFacadeException("Configuration " + categoryOrLogger.getNodeName() + + " element contains neither priority nor level child"); + } + return levelElement; + } + + private static class QpidLog4JSaxErrorHandler implements ErrorHandler + { + public void error(SAXParseException e) throws SAXException + { + if(LOGGER != null) + { + LOGGER.warn(constructMessage("Error parsing XML file", e)); + } + else + { + System.err.println(constructMessage("Error parsing XML file", e)); + } + } + + public void fatalError(SAXParseException e) throws SAXException + { + throw new SAXException(constructMessage("Fatal error parsing XML file", e)); + } + + public void warning(SAXParseException e) throws SAXException + { + if(LOGGER != null) + { + LOGGER.warn(constructMessage("Warning parsing XML file", e)); + } + else + { + System.err.println(constructMessage("Warning parsing XML file", e)); + } + } + + private static String constructMessage(final String msg, final SAXParseException ex) + { + return msg + ": Line " + ex.getLineNumber()+" column " +ex.getColumnNumber() + ": " + ex.getMessage(); + } + } +} + diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties index ac77f674f2..7924be28d3 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties @@ -18,16 +18,21 @@ # # Default File used for all non-defined locales. # -STARTUP = MNG-1001 : Startup +# 0 - Management Type +STARTUP = MNG-1001 : {0} Management Startup # 0 - Service # 1 - Port LISTENING = MNG-1002 : Starting : {0} : Listening on port {1,number,#} # 0 - Service # 1 - Port SHUTTING_DOWN = MNG-1003 : Shutting down : {0} : port {1,number,#} -READY = MNG-1004 : Ready[ : Using the platform JMX Agent] -STOPPED = MNG-1005 : Stopped +# 0 - Management Type +READY = MNG-1004 : {0} Management Ready +# 0 - Management Type +STOPPED = MNG-1005 : {0} Management Stopped # 0 - Path SSL_KEYSTORE = MNG-1006 : Using SSL Keystore : {0} +# 0 - Username OPEN = MNG-1007 : Open : User {0} +# 0 - Username CLOSE = MNG-1008 : Close : User {0} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java index 859d7e2a27..bcb9cb2ac4 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java @@ -76,7 +76,7 @@ public class ChannelLogSubject extends AbstractLogSubject setLogStringWithFormat(CHANNEL_FORMAT, connection == null ? -1L : connection.getConnectionId(), session.getAuthorizedPrincipal() == null ? "?" : session.getAuthorizedPrincipal().getName(), - (connection == null || connection.getConfig() == null) ? "?" : connection.getConfig().getAddress(), + (connection == null || connection.getRemoteAddressString() == null) ? "?" : connection.getRemoteAddressString(), session.getVirtualHost().getName(), session.getChannel()); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/LogSubjectFormat.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/LogSubjectFormat.java index 28c4f0d52a..7611ee1a88 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/LogSubjectFormat.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/LogSubjectFormat.java @@ -32,10 +32,18 @@ package org.apache.qpid.server.logging.subjects; public class LogSubjectFormat { + private LogSubjectFormat() { } + /** + * LOG FORMAT for the ManagementActors, + * 0 - User ID + * 1 - IP[:Port] + */ + public static final String MANAGEMENT_FORMAT = "mng:{0}({1})"; + /** * LOG FORMAT for the Subscription Log Subject * 0 - Subscription ID diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java index 2cc1a92853..e01f20d54f 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java @@ -342,6 +342,14 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData { private final AMQPDescribedTypeRegistry _typeRegistry = AMQPDescribedTypeRegistry.newInstance(); + private MetaDataFactory() + { + _typeRegistry.registerTransportLayer(); + _typeRegistry.registerMessagingLayer(); + _typeRegistry.registerTransactionLayer(); + _typeRegistry.registerSecurityLayer(); + } + public MessageMetaData_1_0 createMetaData(ByteBuffer buf) { ValueHandler valueHandler = new ValueHandler(_typeRegistry); @@ -354,7 +362,8 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData try { ByteBuffer encodedBuf = buf.duplicate(); - sections.add((Section) valueHandler.parse(buf)); + Object parse = valueHandler.parse(buf); + sections.add((Section) parse); encodedBuf.limit(buf.position()); encodedSections.add(encodedBuf); diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java index 6000886956..417f6036ab 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java @@ -24,6 +24,9 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.group.GroupPrincipalAccessor; + public interface AuthenticationProvider extends ConfiguredObject { @@ -52,4 +55,15 @@ public interface AuthenticationProvider extends ConfiguredObject TYPE)); //children Collection getVirtualHostPortBindings(); + + String getName(); + + /** + * A temporary method to create SubjectCreator. + * + * TODO: move all the functionality from SubjectCreator into AuthenticationProvider + */ + SubjectCreator getSubjectCreator(); + + void setGroupAccessor(GroupPrincipalAccessor groupPrincipalAccessor); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java index 08b01a1b65..fbecf1965b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java @@ -20,12 +20,20 @@ */ package org.apache.qpid.server.model; +import java.net.SocketAddress; import java.security.AccessControlException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Map; +import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; + public interface Broker extends ConfiguredObject { @@ -44,9 +52,49 @@ public interface Broker extends ConfiguredObject String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; + String DEFAULT_AUTHENTICATION_PROVIDER = "defaultAuthenticationProvider"; + String DEFAULT_VIRTUAL_HOST = "defaultVirtualHost"; + + String ALERT_THRESHOLD_MESSAGE_AGE = "alertThresholdMessageAge"; + String ALERT_THRESHOLD_MESSAGE_COUNT = "alertThresholdMessageCount"; + String ALERT_THRESHOLD_QUEUE_DEPTH = "alertThresholdQueueDepth"; + String ALERT_THRESHOLD_MESSAGE_SIZE = "alertThresholdMessageSize"; + String ALERT_REPEAT_GAP = "alertRepeatGap"; + String FLOW_CONTROL_SIZE_BYTES = "queueFlowControlSizeBytes"; + String FLOW_CONTROL_RESUME_SIZE_BYTES = "queueFlowResumeSizeBytes"; + String MAXIMUM_DELIVERY_ATTEMPTS = "maximumDeliveryAttempts"; + String DEAD_LETTER_QUEUE_ENABLED = "deadLetterQueueEnabled"; + String HOUSEKEEPING_CHECK_PERIOD = "housekeepingCheckPeriod"; + + String SESSION_COUNT_LIMIT = "sessionCountLimit"; + String HEART_BEAT_DELAY = "heartBeatDelay"; + String STATISTICS_REPORTING_PERIOD = "statisticsReportingPeriod"; + String STATISTICS_REPORTING_RESET_ENABLED = "statisticsReportingResetEnabled"; + + /* + * A temporary attribute to pass the path to ACL file. + * TODO: It should be a part of AuthorizationProvider. + */ + String ACL_FILE = "aclFile"; + + /* + * A temporary attributes to set the broker default key/trust stores. + * TODO: Remove them after adding a full support to configure KeyStore/TrustStore via management layers. + */ + String KEY_STORE_PATH = "keyStorePath"; + String KEY_STORE_PASSWORD = "keyStorePassword"; + String KEY_STORE_CERT_ALIAS = "keyStoreCertAlias"; + String TRUST_STORE_PATH = "trustStorePath"; + String TRUST_STORE_PASSWORD = "trustStorePassword"; + + /* + * A temporary attributes to set the broker group file. + * TODO: Remove them after adding a full support to configure authorization providers via management layers. + */ + String GROUP_FILE = "groupFile"; // Attributes - public static final Collection AVAILABLE_ATTRIBUTES = + Collection AVAILABLE_ATTRIBUTES = Collections.unmodifiableList( Arrays.asList(BUILD_VERSION, BYTES_RETAINED, @@ -62,7 +110,32 @@ public interface Broker extends ConfiguredObject NAME, STATE, TIME_TO_LIVE, - UPDATED)); + UPDATED, + DEFAULT_AUTHENTICATION_PROVIDER, + DEFAULT_VIRTUAL_HOST, + ALERT_THRESHOLD_MESSAGE_AGE, + ALERT_THRESHOLD_MESSAGE_COUNT, + ALERT_THRESHOLD_QUEUE_DEPTH, + ALERT_THRESHOLD_MESSAGE_SIZE, + ALERT_REPEAT_GAP, + FLOW_CONTROL_SIZE_BYTES, + FLOW_CONTROL_RESUME_SIZE_BYTES, + MAXIMUM_DELIVERY_ATTEMPTS, + DEAD_LETTER_QUEUE_ENABLED, + HOUSEKEEPING_CHECK_PERIOD, + SESSION_COUNT_LIMIT, + HEART_BEAT_DELAY, + STATISTICS_REPORTING_PERIOD, + STATISTICS_REPORTING_RESET_ENABLED, + + ACL_FILE, + KEY_STORE_PATH, + KEY_STORE_PASSWORD, + KEY_STORE_CERT_ALIAS, + TRUST_STORE_PATH, + TRUST_STORE_PASSWORD, + GROUP_FILE + )); //children Collection < VirtualHost > getVirtualHosts(); @@ -75,6 +148,49 @@ public interface Broker extends ConfiguredObject LifetimePolicy lifetime, long ttl, Map attributes) throws AccessControlException, IllegalArgumentException; - void deleteVirtualHost(VirtualHost virtualHost) - throws AccessControlException, IllegalStateException; + AuthenticationProvider getDefaultAuthenticationProvider(); + + Collection getGroupProviders(); + + /** + * A temporary hack to expose root message logger via broker instance. + * TODO We need a better way to do operational logging, for example, via logging listeners + */ + RootMessageLogger getRootMessageLogger(); + + /** + * A temporary hack to expose security manager via broker instance. + * TODO We need to add and implement an authorization provider configured object instead + */ + SecurityManager getSecurityManager(); + + /** + * TODO: A temporary hack to expose log recorder via broker instance. + */ + LogRecorder getLogRecorder(); + + VirtualHost findVirtualHostByName(String name); + + /** + * Get the SubjectCreator for the given socket address. + * TODO: move the authentication related functionality into host aliases and AuthenticationProviders + * + * @param address The (listening) socket address for which the AuthenticationManager is required + */ + SubjectCreator getSubjectCreator(SocketAddress localAddress); + + Collection getKeyStores(); + + Collection getTrustStores(); + + /* + * TODO: Remove this method. Eventually the broker will become a registry. + */ + VirtualHostRegistry getVirtualHostRegistry(); + + KeyStore getDefaultKeyStore(); + + TrustStore getDefaultTrustStore(); + + TaskExecutor getTaskExecutor(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java index 78b98faffe..bd7da962ba 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java @@ -36,4 +36,5 @@ public interface ConfigurationChangeListener void childRemoved(ConfiguredObject object, ConfiguredObject child); + void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java index 414b2d083a..d567a3aa44 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java @@ -25,6 +25,9 @@ import java.util.Collection; import java.util.Map; import java.util.UUID; +/** + * An object that can be "managed" (eg via the web interface) and usually read from configuration. + */ public interface ConfiguredObject { @@ -47,7 +50,7 @@ public interface ConfiguredObject * Attempt to change the name of the object * * Request a change to the name of the object. The caller must pass in the name it believes the object currently - * has. If the current name differes from this expected value, then no name change will occur + * has. If the current name differs from this expected value, then no name change will occur * * @param currentName the name the caller believes the object to have * @param desiredName the name the caller would like the object to have @@ -198,13 +201,24 @@ public interface ConfiguredObject /** - * Return the value for the given attribute + * Return the value for the given attribute name. The actual attribute value + * is returned if the configured object has such attribute set. If not, the + * value is looked default attributes. * - * @param name the name of the attribute - * @return the value of the attribute at the object (or null if the attribute is not set + * @param name + * the name of the attribute + * @return the value of the attribute at the object (or null if the + * attribute value is set neither on object itself no in defaults) */ Object getAttribute(String name); + /** + * Return the map containing only explicitly set attributes + * + * @return the map with the attributes + */ + Map getActualAttributes(); + /** * Set the value of an attribute * diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Group.java b/java/broker/src/main/java/org/apache/qpid/server/model/Group.java new file mode 100644 index 0000000000..aacd515107 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Group.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface Group extends ConfiguredObject +{ + String CREATED = "created"; + String DURABLE = "durable"; + String ID = "id"; + String LIFETIME_POLICY = "lifetimePolicy"; + String NAME = "name"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + String UPDATED = "updated"; + + // Attributes + public static final Collection AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED + )); + + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/GroupMember.java b/java/broker/src/main/java/org/apache/qpid/server/model/GroupMember.java new file mode 100644 index 0000000000..6832cc6fa6 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/GroupMember.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface GroupMember extends ConfiguredObject +{ + String CREATED = "created"; + String DURABLE = "durable"; + String ID = "id"; + String LIFETIME_POLICY = "lifetimePolicy"; + String NAME = "name"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + String UPDATED = "updated"; + + // Attributes + public static final Collection AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED + )); + + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/GroupProvider.java b/java/broker/src/main/java/org/apache/qpid/server/model/GroupProvider.java new file mode 100644 index 0000000000..9016f97927 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/GroupProvider.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +import java.security.Principal; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +public interface GroupProvider extends ConfiguredObject +{ + public static final String ID = "id"; + public static final String DESCRIPTION = "description"; + public static final String NAME = "name"; + public static final String STATE = "state"; + public static final String DURABLE = "durable"; + public static final String LIFETIME_POLICY = "lifetimePolicy"; + public static final String TIME_TO_LIVE = "timeToLive"; + public static final String CREATED = "created"; + public static final String UPDATED = "updated"; + public static final String TYPE = "type"; + + public static final Collection AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList(ID, + NAME, + DESCRIPTION, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + TYPE)); + + Set getGroupPrincipalsForUser(String username); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java b/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java new file mode 100644 index 0000000000..959714656b --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface KeyStore extends TrustStore +{ + + String CERTIFICATE_ALIAS = "certificateAlias"; + + public static final Collection AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + DESCRIPTION, + PATH, + PASSWORD, + TYPE, + KEY_MANAGER_FACTORY_ALGORITHM, + CERTIFICATE_ALIAS + )); + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Model.java b/java/broker/src/main/java/org/apache/qpid/server/model/Model.java index 36179fc105..2c05dce9cb 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/Model.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Model.java @@ -47,6 +47,10 @@ public class Model addRelationship(Broker.class, VirtualHost.class); addRelationship(Broker.class, Port.class); addRelationship(Broker.class, AuthenticationProvider.class); + addRelationship(Broker.class, GroupProvider.class); + addRelationship(Broker.class, TrustStore.class); + addRelationship(Broker.class, KeyStore.class); + addRelationship(Broker.class, Plugin.class); addRelationship(VirtualHost.class, Exchange.class); addRelationship(VirtualHost.class, Queue.class); @@ -54,6 +58,10 @@ public class Model addRelationship(VirtualHost.class, VirtualHostAlias.class); addRelationship(AuthenticationProvider.class, User.class); + addRelationship(User.class, GroupMember.class); + + addRelationship(GroupProvider.class, Group.class); + addRelationship(Group.class, GroupMember.class); addRelationship(Connection.class, Session.class); diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Plugin.java b/java/broker/src/main/java/org/apache/qpid/server/model/Plugin.java new file mode 100644 index 0000000000..b9503a5841 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Plugin.java @@ -0,0 +1,52 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface Plugin extends ConfiguredObject +{ + //Hack, using it for the class name only for consistency with the other things. + String CREATED = "created"; + String DURABLE = "durable"; + String ID = "id"; + String LIFETIME_POLICY = "lifetimePolicy"; + String NAME = "name"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + String UPDATED = "updated"; + + // Attributes + public static final Collection AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED + )); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Port.java b/java/broker/src/main/java/org/apache/qpid/server/model/Port.java index 50c0ebcd14..2f94c3cab7 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/Port.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Port.java @@ -39,6 +39,16 @@ public interface Port extends ConfiguredObject String PORT = "port"; String PROTOCOLS = "protocols"; String TRANSPORTS = "transports"; + String TCP_NO_DELAY = "tcpNoDelay"; + String SEND_BUFFER_SIZE = "sendBufferSize"; + String RECEIVE_BUFFER_SIZE = "receiveBufferSize"; + String NEED_CLIENT_AUTH = "needClientAuth"; + String WANT_CLIENT_AUTH = "wantClientAuth"; + + /** + * TODO: rename it to AUTHENTICATION_MANAGER_ID or introduce relationships + */ + String AUTHENTICATION_MANAGER = "authenticationManager"; // Attributes public static final Collection AVAILABLE_ATTRIBUTES = @@ -55,7 +65,13 @@ public interface Port extends ConfiguredObject BINDING_ADDRESS, PORT, PROTOCOLS, - TRANSPORTS + TRANSPORTS, + TCP_NO_DELAY, + SEND_BUFFER_SIZE, + RECEIVE_BUFFER_SIZE, + NEED_CLIENT_AUTH, + WANT_CLIENT_AUTH, + AUTHENTICATION_MANAGER )); @@ -88,4 +104,8 @@ public interface Port extends ConfiguredObject //children Collection getVirtualHostBindings(); Collection getConnections(); + + AuthenticationProvider getAuthenticationProvider(); + + void setAuthenticationProvider(AuthenticationProvider authenticationProvider); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java b/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java index 5d9de69f9a..6cd5eb23a4 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java @@ -20,14 +20,95 @@ */ package org.apache.qpid.server.model; +import java.util.Collection; +import java.util.EnumSet; + +import org.apache.qpid.server.protocol.AmqpProtocolVersion; + public enum Protocol { - AMQP_0_8, - AMQP_0_9, - AMQP_0_9_1, - AMQP_0_10, - AMQP_1_0, - JMX, - HTTP, - HTTPS + AMQP_0_8(ProtocolType.AMQP), + AMQP_0_9(ProtocolType.AMQP), + AMQP_0_9_1(ProtocolType.AMQP), + AMQP_0_10(ProtocolType.AMQP), + AMQP_1_0(ProtocolType.AMQP), + JMX_RMI(ProtocolType.JMX), + HTTP(ProtocolType.HTTP), + HTTPS(ProtocolType.HTTP), + RMI(ProtocolType.RMI); + + private final ProtocolType _protocolType; + + private Protocol(ProtocolType type) + { + _protocolType = type; + } + + public ProtocolType getProtocolType() + { + return _protocolType; + } + + public boolean isAMQP() + { + return _protocolType == ProtocolType.AMQP; + } + + public AmqpProtocolVersion toAmqpProtocolVersion() + { + switch(this) + { + case AMQP_0_8: + return AmqpProtocolVersion.v0_8; + case AMQP_0_9: + return AmqpProtocolVersion.v0_9; + case AMQP_0_9_1: + return AmqpProtocolVersion.v0_9_1; + case AMQP_0_10: + return AmqpProtocolVersion.v0_10; + case AMQP_1_0: + return AmqpProtocolVersion.v1_0_0; + default: + throw new IllegalArgumentException(this + " is not an known AMQP protocol"); + } + } + + public static Protocol valueOfObject(Object protocolObject) + { + Protocol protocol; + if (protocolObject instanceof Protocol) + { + protocol = (Protocol) protocolObject; + } + else + { + try + { + protocol = Protocol.valueOf(String.valueOf(protocolObject)); + } + catch (Exception e) + { + throw new IllegalArgumentException("Can't convert '" + protocolObject + + "' to one of the supported protocols: " + EnumSet.allOf(Protocol.class), e); + } + } + return protocol; + } + + public static boolean hasAmqpProtocol(Collection protocols) + { + for (Protocol protocol : protocols) + { + if (protocol.isAMQP()) + { + return true; + } + } + return false; + } + + public static enum ProtocolType + { + AMQP, HTTP, JMX, RMI; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java b/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java index 03cd46be01..ae6e5ac43a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java @@ -20,8 +20,32 @@ */ package org.apache.qpid.server.model; +import java.util.EnumSet; + public enum Transport { TCP, - SSL + SSL; + + public static Transport valueOfObject(Object transportObject) + { + Transport transport; + if (transportObject instanceof Transport) + { + transport = (Transport) transportObject; + } + else + { + try + { + transport = Transport.valueOf(String.valueOf(transportObject)); + } + catch (Exception e) + { + throw new IllegalArgumentException("Can't convert '" + transportObject + + "' to one of the supported transports: " + EnumSet.allOf(Transport.class), e); + } + } + return transport; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java b/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java new file mode 100644 index 0000000000..0c322ae02f --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java @@ -0,0 +1,65 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface TrustStore extends ConfiguredObject +{ + String ID = "id"; + String NAME = "name"; + String DURABLE = "durable"; + String LIFETIME_POLICY = "lifetimePolicy"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + String CREATED = "created"; + String UPDATED = "updated"; + String DESCRIPTION = "description"; + + String PATH = "path"; + String PASSWORD = "password"; + String TYPE = "type"; + String KEY_MANAGER_FACTORY_ALGORITHM = "keyManagerFactoryAlgorithm"; + + public static final Collection AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + DESCRIPTION, + PATH, + PASSWORD, + TYPE, + KEY_MANAGER_FACTORY_ALGORITHM + )); + + public String getPassword(); + + public void setPassword(String password); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java b/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java index 36b6a454dc..bcedd91596 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java @@ -63,6 +63,11 @@ public class UUIDGenerator return createUUID(User.class.getName(), authenticationProviderName, userName); } + public static UUID generateGroupUUID(String groupProviderName, String groupName) + { + return createUUID(Group.class.getName(), groupProviderName, groupName); + } + public static UUID generateVhostUUID(String virtualHostName) { return createUUID(VirtualHost.class.getName(), virtualHostName); @@ -77,4 +82,14 @@ public class UUIDGenerator { return createUUID(Consumer.class.getName(), virtualHostName, queueName, connectionRemoteAddress, channelNumber, consumerName); } + + public static UUID generateGroupMemberUUID(String groupProviderName, String groupName, String groupMemberName) + { + return createUUID(GroupMember.class.getName(), groupProviderName, groupName, groupMemberName); + } + + public static UUID generateBrokerChildUUID(String type, String childName) + { + return createUUID(type, childName); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/User.java b/java/broker/src/main/java/org/apache/qpid/server/model/User.java index d97bf46d31..675dc8f0d3 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/User.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/User.java @@ -52,8 +52,6 @@ public interface User extends ConfiguredObject PASSWORD )); - public String getPassword(); - public void setPassword(String password); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java index 24a3d43386..5f4ec1d3a8 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java @@ -21,6 +21,9 @@ package org.apache.qpid.server.model; import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.store.MessageStore; + import java.security.AccessControlException; import java.util.Arrays; import java.util.Collection; @@ -60,17 +63,16 @@ public interface VirtualHost extends ConfiguredObject String ALERT_THRESHOLD_QUEUE_DEPTH_BYTES = "alertThresholdQueueDepthBytes"; String ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES = "alertThresholdQueueDepthMessages"; String DEAD_LETTER_QUEUE_ENABLED = "deadLetterQueueEnabled"; - String FEDERATION_TAG = "federationTag"; String HOUSEKEEPING_CHECK_PERIOD = "housekeepingCheckPeriod"; String MAXIMUM_DELIVERY_ATTEMPTS = "maximumDeliveryAttempts"; String QUEUE_FLOW_CONTROL_SIZE_BYTES = "queueFlowControlSizeBytes"; String QUEUE_FLOW_RESUME_SIZE_BYTES = "queueFlowResumeSizeBytes"; - String STORE_CONFIGURATION = "storeConfiguration"; String STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE = "storeTransactionIdleTimeoutClose"; String STORE_TRANSACTION_IDLE_TIMEOUT_WARN = "storeTransactionIdleTimeoutWarn"; String STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE = "storeTransactionOpenTimeoutClose"; String STORE_TRANSACTION_OPEN_TIMEOUT_WARN = "storeTransactionOpenTimeoutWarn"; String STORE_TYPE = "storeType"; + String STORE_PATH = "storePath"; String SUPPORTED_EXCHANGE_TYPES = "supportedExchangeTypes"; String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes"; String CREATED = "created"; @@ -81,6 +83,8 @@ public interface VirtualHost extends ConfiguredObject String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; + String CONFIG_PATH = "configPath"; + // Attributes public static final Collection AVAILABLE_ATTRIBUTES = Collections.unmodifiableList( @@ -96,13 +100,12 @@ public interface VirtualHost extends ConfiguredObject SUPPORTED_EXCHANGE_TYPES, SUPPORTED_QUEUE_TYPES, DEAD_LETTER_QUEUE_ENABLED, - FEDERATION_TAG, HOUSEKEEPING_CHECK_PERIOD, MAXIMUM_DELIVERY_ATTEMPTS, QUEUE_FLOW_CONTROL_SIZE_BYTES, QUEUE_FLOW_RESUME_SIZE_BYTES, STORE_TYPE, - STORE_CONFIGURATION, + STORE_PATH, STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, STORE_TRANSACTION_IDLE_TIMEOUT_WARN, STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, @@ -111,7 +114,8 @@ public interface VirtualHost extends ConfiguredObject ALERT_THRESHOLD_MESSAGE_AGE, ALERT_THRESHOLD_MESSAGE_SIZE, ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, - ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES)); + ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, + CONFIG_PATH)); @@ -149,4 +153,12 @@ public interface VirtualHost extends ConfiguredObject } void executeTransaction(TransactionalOperation op); + + /** + * A temporary hack to expose host security manager. + * TODO We need to add and implement an authorization provider configured object instead + */ + SecurityManager getSecurityManager(); + + MessageStore getMessageStore(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java index 7d6aa9b2cb..73e1f1e970 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java @@ -24,12 +24,18 @@ import java.security.AccessControlException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; + import org.apache.qpid.server.model.ConfigurationChangeListener; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.IllegalStateTransitionException; import org.apache.qpid.server.model.State; +import org.apache.qpid.server.configuration.updater.ChangeStateTask; +import org.apache.qpid.server.configuration.updater.CreateChildTask; +import org.apache.qpid.server.configuration.updater.SetAttributeTask; +import org.apache.qpid.server.configuration.updater.TaskExecutor; abstract class AbstractAdapter implements ConfiguredObject { @@ -40,134 +46,78 @@ abstract class AbstractAdapter implements ConfiguredObject new ArrayList(); private final UUID _id; + private final Map _defaultAttributes = new HashMap(); + private final TaskExecutor _taskExecutor; - protected AbstractAdapter(UUID id) + protected AbstractAdapter(UUID id, Map defaults, Map attributes, TaskExecutor taskExecutor) { + _taskExecutor = taskExecutor; _id = id; - } - - static String getStringAttribute(String name, Map attributes, String defaultVal) - { - final Object value = attributes.get(name); - return value == null ? defaultVal : String.valueOf(value); - } - - static Map getMapAttribute(String name, Map attributes, Map defaultVal) - { - final Object value = attributes.get(name); - if(value == null) - { - return defaultVal; - } - else if(value instanceof Map) + if (attributes != null) { - return (Map) value; + Collection names = getAttributeNames(); + for (String name : names) + { + if (attributes.containsKey(name)) + { + _attributes.put(name, attributes.get(name)); + } + } } - else + if (defaults != null) { - throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Map"); + _defaultAttributes.putAll(defaults); } } - - static E getEnumAttribute(Class clazz, String name, Map attributes, E defaultVal) + protected AbstractAdapter(UUID id, TaskExecutor taskExecutor) { - Object obj = attributes.get(name); - if(obj == null) - { - return defaultVal; - } - else if(clazz.isInstance(obj)) - { - return (E) obj; - } - else if(obj instanceof String) - { - return (E) Enum.valueOf(clazz, (String)obj); - } - else - { - throw new IllegalArgumentException("Value for attribute " + name + " is not of required type " + clazz.getSimpleName()); - } + this(id, null, null, taskExecutor); } - static Boolean getBooleanAttribute(String name, Map attributes, Boolean defaultValue) + public final UUID getId() { - Object obj = attributes.get(name); - if(obj == null) - { - return defaultValue; - } - else if(obj instanceof Boolean) - { - return (Boolean) obj; - } - else if(obj instanceof String) - { - return Boolean.parseBoolean((String) obj); - } - else - { - throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Boolean"); - } + return _id; } - static Integer getIntegerAttribute(String name, Map attributes, Integer defaultValue) + public State getDesiredState() { - Object obj = attributes.get(name); - if(obj == null) - { - return defaultValue; - } - else if(obj instanceof Number) - { - return ((Number) obj).intValue(); - } - else if(obj instanceof String) - { - return Integer.valueOf((String) obj); - } - else - { - throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Integer"); - } + return null; //TODO } - static Long getLongAttribute(String name, Map attributes, Long defaultValue) + @Override + public final State setDesiredState(final State currentState, final State desiredState) + throws IllegalStateTransitionException, AccessControlException { - Object obj = attributes.get(name); - if(obj == null) - { - return defaultValue; - } - else if(obj instanceof Number) + if (_taskExecutor.isTaskExecutorThread()) { - return ((Number) obj).longValue(); - } - else if(obj instanceof String) - { - return Long.valueOf((String) obj); + if (setState(currentState, desiredState)) + { + notifyStateChanged(currentState, desiredState); + } } else { - throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Long"); + _taskExecutor.submitAndWait(new ChangeStateTask(this, currentState, desiredState)); } + return getActualState(); } - public final UUID getId() - { - return _id; - } + /** + * @return true when the state has been successfully updated to desiredState or false otherwise + */ + protected abstract boolean setState(State currentState, State desiredState); - public State getDesiredState() + protected void notifyStateChanged(final State currentState, final State desiredState) { - return null; //TODO - } - - public State setDesiredState(final State currentState, final State desiredState) - throws IllegalStateTransitionException, AccessControlException - { - return null; //TODO + synchronized (_changeListeners) + { + List copy = new ArrayList(_changeListeners); + for(ConfigurationChangeListener listener : copy) + { + listener.stateChanged(this, currentState, desiredState); + } + } } public void addChangeListener(final ConfigurationChangeListener listener) @@ -176,7 +126,7 @@ abstract class AbstractAdapter implements ConfiguredObject { throw new NullPointerException("Cannot add a null listener"); } - synchronized (this) + synchronized (_changeListeners) { if(!_changeListeners.contains(listener)) { @@ -191,39 +141,76 @@ abstract class AbstractAdapter implements ConfiguredObject { throw new NullPointerException("Cannot remove a null listener"); } - synchronized (this) + synchronized (_changeListeners) { return _changeListeners.remove(listener); } } - protected void childAdded(ConfiguredObject child) { - synchronized (this) + synchronized (_changeListeners) { - for(ConfigurationChangeListener listener : _changeListeners) + List copy = new ArrayList(_changeListeners); + for(ConfigurationChangeListener listener : copy) { listener.childAdded(this, child); } } } - protected void childRemoved(ConfiguredObject child) { - synchronized (this) + synchronized (_changeListeners) { - for(ConfigurationChangeListener listener : _changeListeners) + List copy = new ArrayList(_changeListeners); + for(ConfigurationChangeListener listener : copy) { listener.childRemoved(this, child); } } } - public Object getAttribute(final String name) + protected void attributeSet(String attrinuteName, Object oldAttributeValue, Object newAttributeValue) { - synchronized (this) + synchronized (_changeListeners) + { + List copy = new ArrayList(_changeListeners); + for(ConfigurationChangeListener listener : copy) + { + listener.attributeSet(this, attrinuteName, oldAttributeValue, newAttributeValue); + } + } + } + + private final Object getDefaultAttribute(String name) + { + return _defaultAttributes.get(name); + } + + @Override + public Object getAttribute(String name) + { + Object value = getActualAttribute(name); + if (value == null) + { + value = getDefaultAttribute(name); + } + return value; + } + + @Override + public final Map getActualAttributes() + { + synchronized (_attributes) + { + return new HashMap(_attributes); + } + } + + private Object getActualAttribute(final String name) + { + synchronized (_attributes) { return _attributes.get(name); } @@ -232,25 +219,41 @@ abstract class AbstractAdapter implements ConfiguredObject public Object setAttribute(final String name, final Object expected, final Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException { - synchronized (this) + if (_taskExecutor.isTaskExecutorThread()) { - Object currentValue = _attributes.get(name); + if (changeAttribute(name, expected, desired)) + { + attributeSet(name, expected, desired); + } + } + else + { + _taskExecutor.submitAndWait(new SetAttributeTask(this, name, expected, desired)); + } + return getAttribute(name); + } + + protected boolean changeAttribute(final String name, final Object expected, final Object desired) + { + synchronized (_attributes) + { + Object currentValue = getAttribute(name); if((currentValue == null && expected == null) || (currentValue != null && currentValue.equals(expected))) { _attributes.put(name, desired); - return desired; + return true; } else { - return currentValue; + return false; } } } public T getParent(final Class clazz) { - synchronized (this) + synchronized (_parents) { return (T) _parents.get(clazz); } @@ -258,7 +261,7 @@ abstract class AbstractAdapter implements ConfiguredObject protected void addParent(Class clazz, T parent) { - synchronized (this) + synchronized (_parents) { _parents.put(clazz, parent); } @@ -280,4 +283,40 @@ abstract class AbstractAdapter implements ConfiguredObject } } + @Override + public String toString() + { + return getClass().getSimpleName() + " [id=" + _id + ", name=" + getName() + "]"; + } + + @SuppressWarnings("unchecked") + @Override + public C createChild(Class childClass, Map attributes, ConfiguredObject... otherParents) + { + if (_taskExecutor.isTaskExecutorThread()) + { + C child = addChild(childClass, attributes, otherParents); + if (child != null) + { + childAdded(child); + } + return child; + } + else + { + return (C)_taskExecutor.submitAndWait(new CreateChildTask(this, childClass, attributes, otherParents)); + } + } + + protected C addChild(Class childClass, Map attributes, ConfiguredObject... otherParents) + { + throw new UnsupportedOperationException(); + } + + + protected TaskExecutor getTaskExecutor() + { + return _taskExecutor; + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java new file mode 100644 index 0000000000..ebd98f915d --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractKeyStoreAdapter.java @@ -0,0 +1,198 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.KeyStore; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.util.MapValueConverter; + +public abstract class AbstractKeyStoreAdapter extends AbstractAdapter +{ + private String _name; + private String _password; + + protected AbstractKeyStoreAdapter(UUID id, Broker broker, Map attributes) + { + super(id, broker.getTaskExecutor()); + addParent(Broker.class, broker); + _name = MapValueConverter.getStringAttribute(TrustStore.NAME, attributes); + _password = MapValueConverter.getStringAttribute(TrustStore.PASSWORD, attributes); + setMandatoryAttribute(TrustStore.PATH, attributes); + setOptionalAttribute(TrustStore.TYPE, attributes); + setOptionalAttribute(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, attributes); + setOptionalAttribute(TrustStore.DESCRIPTION, attributes); + } + + @Override + public String getName() + { + return _name; + } + + @Override + public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException + { + throw new IllegalStateException(); + } + + @Override + public State getActualState() + { + return State.ACTIVE; + } + + @Override + public boolean isDurable() + { + return true; + } + + @Override + public void setDurable(boolean durable) throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) throws IllegalStateException, AccessControlException, + IllegalArgumentException + { + throw new IllegalStateException(); + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public Collection getChildren(Class clazz) + { + return Collections.emptySet(); + } + + @Override + public C createChild(Class childClass, Map attributes, ConfiguredObject... otherParents) + { + throw new UnsupportedOperationException(); + } + + @Override + public Object getAttribute(String name) + { + if(KeyStore.ID.equals(name)) + { + return getId(); + } + else if(KeyStore.NAME.equals(name)) + { + return getName(); + } + else if(KeyStore.STATE.equals(name)) + { + return getActualState(); + } + else if(KeyStore.DURABLE.equals(name)) + { + return isDurable(); + } + else if(KeyStore.LIFETIME_POLICY.equals(name)) + { + return getLifetimePolicy(); + } + else if(KeyStore.TIME_TO_LIVE.equals(name)) + { + return getTimeToLive(); + } + else if(KeyStore.CREATED.equals(name)) + { + + } + else if(KeyStore.UPDATED.equals(name)) + { + + } + else if(KeyStore.PASSWORD.equals(name)) + { + return null; // for security reasons we don't expose the password + } + return super.getAttribute(name); + } + + @Override + protected boolean setState(State currentState, State desiredState) + { + return false; + } + + public String getPassword() + { + return _password; + } + + public void setPassword(String password) + { + _password = password; + } + + private void setMandatoryAttribute(String name, Map attributeValues) + { + changeAttribute(name, null, MapValueConverter.getStringAttribute(name, attributeValues)); + } + + private void setOptionalAttribute(String name, Map attributeValues) + { + if (attributeValues.get(name) != null) + { + changeAttribute(name, null, MapValueConverter.getStringAttribute(name, attributeValues)); + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractPluginAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractPluginAdapter.java new file mode 100644 index 0000000000..ed4af9881f --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractPluginAdapter.java @@ -0,0 +1,152 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; + +public abstract class AbstractPluginAdapter extends AbstractAdapter implements Plugin +{ + + protected AbstractPluginAdapter(UUID id, Map defaults, Map attributes, TaskExecutor taskExecutor) + { + super(id, defaults, attributes, taskExecutor); + } + + @Override + public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException + { + throw new UnsupportedOperationException(); + } + + @Override + public State getActualState() + { + return null; + } + + @Override + public boolean isDurable() + { + return true; + } + + @Override + public void setDurable(boolean durable) throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new UnsupportedOperationException(); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) throws IllegalStateException, + AccessControlException, IllegalArgumentException + { + throw new UnsupportedOperationException(); + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) throws IllegalStateException, AccessControlException, + IllegalArgumentException + { + throw new UnsupportedOperationException(); + } + + @Override + public Statistics getStatistics() + { + return null; + } + + @Override + public Collection getChildren(Class clazz) + { + return Collections.emptyList(); + } + + @Override + public C createChild(Class childClass, Map attributes, + ConfiguredObject... otherParents) + { + throw new UnsupportedOperationException(); + } + + @Override + public Collection getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + + @Override + public Object getAttribute(String name) + { + if (ID.equals(name)) + { + return getId(); + } + else if (STATE.equals(name)) + { + return getActualState(); + } + else if (DURABLE.equals(name)) + { + return isDurable(); + } + else if (LIFETIME_POLICY.equals(name)) + { + return getLifetimePolicy(); + } + else if (TIME_TO_LIVE.equals(name)) + { + return getTimeToLive(); + } + else if (CREATED.equals(name)) + { + + } + else if (UPDATED.equals(name)) + { + + } + return super.getAttribute(name); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java new file mode 100644 index 0000000000..2f7e89bb2b --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java @@ -0,0 +1,251 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.security.GeneralSecurityException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import javax.net.ssl.SSLContext; + +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.BrokerMessages; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.KeyStore; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; +import org.apache.qpid.ssl.SSLContextFactory; +import org.apache.qpid.transport.NetworkTransportConfiguration; +import org.apache.qpid.transport.network.IncomingNetworkTransport; + +public class AmqpPortAdapter extends PortAdapter +{ + private final Broker _broker; + private IncomingNetworkTransport _transport; + + public AmqpPortAdapter(UUID id, Broker broker, Map attributes, Map defaultAttributes, TaskExecutor taskExecutor) + { + super(id, broker, attributes, defaultAttributes, taskExecutor); + _broker = broker; + } + + @Override + protected void onActivate() + { + Collection transports = getTransports(); + Set supported = convertFromModelProtocolsToAmqp(getProtocols()); + + SSLContext sslContext = null; + if (transports.contains(Transport.SSL)) + { + sslContext = createSslContext(); + } + + AmqpProtocolVersion defaultSupportedProtocolReply = getDefaultAmqpSupportedReply(); + + String bindingAddress = (String) getAttribute(Port.BINDING_ADDRESS); + if (WILDCARD_ADDRESS.equals(bindingAddress)) + { + bindingAddress = null; + } + Integer port = (Integer) getAttribute(Port.PORT); + InetSocketAddress bindingSocketAddress = null; + if ( bindingAddress == null ) + { + bindingSocketAddress = new InetSocketAddress(port); + } + else + { + bindingSocketAddress = new InetSocketAddress(bindingAddress, port); + } + + final NetworkTransportConfiguration settings = new ServerNetworkTransportConfiguration( + bindingSocketAddress, (Boolean)getAttribute(TCP_NO_DELAY), + (Integer)getAttribute(SEND_BUFFER_SIZE), (Integer)getAttribute(RECEIVE_BUFFER_SIZE), + (Boolean)getAttribute(NEED_CLIENT_AUTH), (Boolean)getAttribute(WANT_CLIENT_AUTH)); + + _transport = org.apache.qpid.transport.network.Transport.getIncomingTransportInstance(); + final MultiVersionProtocolEngineFactory protocolEngineFactory = new MultiVersionProtocolEngineFactory( + _broker, supported, defaultSupportedProtocolReply); + + _transport.accept(settings, protocolEngineFactory, sslContext); + CurrentActor.get().message(BrokerMessages.LISTENING(getTransports().toString(), getPort())); + } + + @Override + protected void onStop() + { + if (_transport != null) + { + CurrentActor.get().message(BrokerMessages.SHUTTING_DOWN(getTransports().toString(), getPort())); + _transport.close(); + } + } + + private Set convertFromModelProtocolsToAmqp(Collection modelProtocols) + { + Set amqpProtocols = new HashSet(); + for (Protocol protocol : modelProtocols) + { + amqpProtocols.add(protocol.toAmqpProtocolVersion()); + } + return amqpProtocols; + } + + private SSLContext createSslContext() + { + KeyStore keyStore = _broker.getDefaultKeyStore(); + if (keyStore == null) + { + throw new IllegalConfigurationException("SSL was requested on AMQP port '" + + this.getName() + "' but no key store defined"); + } + + TrustStore trustStore = _broker.getDefaultTrustStore(); + if (((Boolean)getAttribute(NEED_CLIENT_AUTH) || (Boolean)getAttribute(WANT_CLIENT_AUTH)) && trustStore == null) + { + throw new IllegalConfigurationException("Client certificate authentication is enabled on AMQP port '" + + this.getName() + "' but no trust store defined"); + } + + String keystorePath = (String)keyStore.getAttribute(KeyStore.PATH); + String keystorePassword = keyStore.getPassword(); + String keystoreType = (String)keyStore.getAttribute(KeyStore.TYPE); + String keyManagerFactoryAlgorithm = (String)keyStore.getAttribute(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM); + String certAlias = (String)keyStore.getAttribute(KeyStore.CERTIFICATE_ALIAS); + + final SSLContext sslContext; + try + { + if(trustStore != null) + { + String trustStorePassword = trustStore.getPassword(); + String trustStoreType = (String)trustStore.getAttribute(TrustStore.TYPE); + String trustManagerFactoryAlgorithm = (String)trustStore.getAttribute(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM); + String trustStorePath = (String)trustStore.getAttribute(TrustStore.PATH); + + sslContext = SSLContextFactory.buildClientContext(trustStorePath, + trustStorePassword, + trustStoreType, + trustManagerFactoryAlgorithm, + keystorePath, + keystorePassword, keystoreType, keyManagerFactoryAlgorithm, + certAlias); + } + else + { + sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keystoreType, keyManagerFactoryAlgorithm); + } + } + catch (GeneralSecurityException e) + { + throw new RuntimeException("Unable to create SSLContext for key or trust store", e); + } + catch (IOException e) + { + throw new RuntimeException("Unable to create SSLContext - unable to load key/trust store", e); + } + return sslContext; + } + + private AmqpProtocolVersion getDefaultAmqpSupportedReply() + { + String defaultAmqpSupportedReply = System.getProperty(BrokerProperties.PROPERTY_DEFAULT_SUPPORTED_PROTOCOL_REPLY); + if (defaultAmqpSupportedReply != null) + { + return AmqpProtocolVersion.valueOf(defaultAmqpSupportedReply); + } + return null; + } + + + class ServerNetworkTransportConfiguration implements NetworkTransportConfiguration + { + private final InetSocketAddress _bindingSocketAddress; + private final Boolean _tcpNoDelay; + private final Integer _sendBufferSize; + private final Integer _receiveBufferSize; + private final boolean _needClientAuth; + private final boolean _wantClientAuth; + + public ServerNetworkTransportConfiguration( + InetSocketAddress bindingSocketAddress, boolean tcpNoDelay, + int sendBufferSize, int receiveBufferSize, + boolean needClientAuth, boolean wantClientAuth) + { + _bindingSocketAddress = bindingSocketAddress; + _tcpNoDelay = tcpNoDelay; + _sendBufferSize = sendBufferSize; + _receiveBufferSize = receiveBufferSize; + _needClientAuth = needClientAuth; + _wantClientAuth = wantClientAuth; + } + + @Override + public boolean wantClientAuth() + { + return _wantClientAuth; + } + + @Override + public boolean needClientAuth() + { + return _needClientAuth; + } + + @Override + public Boolean getTcpNoDelay() + { + return _tcpNoDelay; + } + + @Override + public Integer getSendBufferSize() + { + return _sendBufferSize; + } + + @Override + public Integer getReceiveBufferSize() + { + return _receiveBufferSize; + } + + @Override + public InetSocketAddress getAddress() + { + return _bindingSocketAddress; + } + }; +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java index 8c2bc98ba7..ac4b0255d5 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java @@ -29,38 +29,50 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; + import javax.security.auth.login.AccountNotFoundException; import org.apache.log4j.Logger; -import org.apache.qpid.server.model.*; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.IllegalStateTransitionException; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.auth.database.PrincipalDatabase; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.group.GroupPrincipalAccessor; +import org.apache.qpid.server.security.SecurityManager; public abstract class AuthenticationProviderAdapter extends AbstractAdapter implements AuthenticationProvider { private static final Logger LOGGER = Logger.getLogger(AuthenticationProviderAdapter.class); - private final BrokerAdapter _broker; private final T _authManager; + protected final Broker _broker; - private AuthenticationProviderAdapter(BrokerAdapter brokerAdapter, - final T authManager) - { - super(UUIDGenerator.generateRandomUUID()); - _broker = brokerAdapter; - _authManager = authManager; - } + private GroupPrincipalAccessor _groupAccessor; - public static AuthenticationProviderAdapter createAuthenticationProviderAdapter(BrokerAdapter brokerAdapter, - final AuthenticationManager authManager) + private Object _type; + + private AuthenticationProviderAdapter(UUID id, Broker broker, final T authManager, Map attributes) { - return authManager instanceof PrincipalDatabaseAuthenticationManager - ? new PrincipalDatabaseAuthenticationManagerAdapter(brokerAdapter, (PrincipalDatabaseAuthenticationManager) authManager) - : new SimpleAuthenticationProviderAdapter(brokerAdapter, authManager); + super(id, null, attributes, broker.getTaskExecutor()); + _authManager = authManager; + _broker = broker; + _type = authManager instanceof PrincipalDatabaseAuthenticationManager? PrincipalDatabaseAuthenticationManager.class.getSimpleName() : AuthenticationManager.class.getSimpleName() ; + addParent(Broker.class, broker); } T getAuthManager() @@ -77,7 +89,7 @@ public abstract class AuthenticationProviderAdapter C createChild(Class childClass, - Map attributes, - ConfiguredObject... otherParents) + public boolean setState(State currentState, State desiredState) + throws IllegalStateTransitionException, AccessControlException { - return null; + if(desiredState == State.DELETED) + { + return true; + } + else if(desiredState == State.ACTIVE) + { + if (_groupAccessor == null) + { + throw new IllegalStateTransitionException("Cannot transit into ACTIVE state with null group accessor!"); + } + _authManager.initialise(); + return true; + } + else if(desiredState == State.STOPPED) + { + _authManager.close(); + return true; + } + return false; } - private static class SimpleAuthenticationProviderAdapter extends AuthenticationProviderAdapter + @Override + public SubjectCreator getSubjectCreator() { + return new SubjectCreator(_authManager, _groupAccessor); + } + + public void setGroupAccessor(GroupPrincipalAccessor groupAccessor) + { + _groupAccessor = groupAccessor; + } + + public static class SimpleAuthenticationProviderAdapter extends AuthenticationProviderAdapter + { + public SimpleAuthenticationProviderAdapter( - BrokerAdapter brokerAdapter, AuthenticationManager authManager) + UUID id, Broker broker, AuthenticationManager authManager, Map attributes) + { + super(id, broker,authManager, attributes); + } + + @Override + public C createChild(Class childClass, + Map attributes, + ConfiguredObject... otherParents) { - super(brokerAdapter,authManager); + throw new UnsupportedOperationException(); } } - private static class PrincipalDatabaseAuthenticationManagerAdapter + public static class PrincipalDatabaseAuthenticationManagerAdapter extends AuthenticationProviderAdapter implements PasswordCredentialManagingAuthenticationProvider { public PrincipalDatabaseAuthenticationManagerAdapter( - BrokerAdapter brokerAdapter, PrincipalDatabaseAuthenticationManager authManager) + UUID id, Broker broker, PrincipalDatabaseAuthenticationManager authManager, Map attributes) { - super(brokerAdapter, authManager); + super(id, broker, authManager, attributes); } @Override public boolean createUser(String username, String password, Map attributes) { - return getPrincipalDatabase().createPrincipal(new UsernamePrincipal(username), password.toCharArray()); + if(getSecurityManager().authoriseUserOperation(Operation.CREATE, username)) + { + return getPrincipalDatabase().createPrincipal(new UsernamePrincipal(username), password.toCharArray()); + } + else + { + throw new AccessControlException("Do not have permission to create new user"); + } } @Override public void deleteUser(String username) throws AccountNotFoundException { - if(getSecurityManager().authoriseMethod(Operation.DELETE, - "UserManagement", - "deleteUser")) + if(getSecurityManager().authoriseUserOperation(Operation.DELETE, username)) { getPrincipalDatabase().deletePrincipal(new UsernamePrincipal(username)); @@ -239,9 +289,9 @@ public abstract class AuthenticationProviderAdapter> users = new HashMap>(); for(Principal principal : getPrincipalDatabase().getUsers()) { - users.put(principal.getName(), Collections.EMPTY_MAP); + users.put(principal.getName(), Collections.emptyMap()); } return users; } + public void reload() throws IOException + { + getPrincipalDatabase().reload(); + } + @Override - public C createChild(Class childClass, + public C addChild(Class childClass, Map attributes, ConfiguredObject... otherParents) { if(childClass == User.class) { - Principal p = new UsernamePrincipal((String) attributes.get("name")); - if(getSecurityManager().authoriseMethod(Operation.UPDATE, "UserManagement", "createUser")) + String username = (String) attributes.get("name"); + String password = (String) attributes.get("password"); + Principal p = new UsernamePrincipal(username); + + if(createUser(username, password,null)) { - if(getPrincipalDatabase().createPrincipal(p, ((String)attributes.get("password")).toCharArray())) - { - return (C) new PrincipalAdapter(p); - } + @SuppressWarnings("unchecked") + C pricipalAdapter = (C) new PrincipalAdapter(p, getTaskExecutor()); + return pricipalAdapter; } else { - throw new AccessControlException("Do not have permission to create a new user"); + //TODO? Silly interface on the PrincipalDatabase at fault + throw new RuntimeException("Failed to create user"); } - } - return super.createChild(childClass, attributes, otherParents); + return super.addChild(childClass, attributes, otherParents); } @Override @@ -313,9 +365,11 @@ public abstract class AuthenticationProviderAdapter principals = new ArrayList(users.size()); for(Principal user : users) { - principals.add(new PrincipalAdapter(user)); + principals.add(new PrincipalAdapter(user, getTaskExecutor())); } - return (Collection) Collections.unmodifiableCollection(principals); + @SuppressWarnings("unchecked") + Collection unmodifiablePrincipals = (Collection) Collections.unmodifiableCollection(principals); + return unmodifiablePrincipals; } else { @@ -328,19 +382,13 @@ public abstract class AuthenticationProviderAdapter _factories; + + public AuthenticationProviderFactory(QpidServiceLoader authManagerFactoryServiceLoader) + { + _factories = authManagerFactoryServiceLoader.atLeastOneInstanceOf(AuthenticationManagerFactory.class); + } + + /** + * Creates {@link AuthenticationProvider} for given ID, {@link Broker} and attributes. + *

+ * The configured {@link AuthenticationManagerFactory}'s are used to try to create the {@link AuthenticationProvider}. + * The first non-null instance is returned. The factories are used in non-deterministic order. + * @param groupPrincipalAccessor TODO + */ + public AuthenticationProvider create(UUID id, Broker broker, Map attributes, GroupPrincipalAccessor groupPrincipalAccessor) + { + for (AuthenticationManagerFactory factory : _factories) + { + AuthenticationManager manager = factory.createInstance(attributes); + if (manager != null) + { + AuthenticationProviderAdapter authenticationProvider; + if (manager instanceof PrincipalDatabaseAuthenticationManager) + { + authenticationProvider = new PrincipalDatabaseAuthenticationManagerAdapter(id, broker, + (PrincipalDatabaseAuthenticationManager) manager, attributes); + } + else + { + authenticationProvider = new SimpleAuthenticationProviderAdapter(id, broker, manager, attributes); + } + authenticationProvider.setGroupAccessor(groupPrincipalAccessor); + return authenticationProvider; + } + } + + throw new IllegalArgumentException("No authentication provider factory found for configuration attributes " + attributes); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java index abd3160686..eb2d0dd7e2 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java @@ -48,7 +48,7 @@ final class BindingAdapter extends AbstractAdapter implements Binding ExchangeAdapter exchangeAdapter, QueueAdapter queueAdapter) { - super(binding.getId()); + super(binding.getId(), queueAdapter.getTaskExecutor()); _binding = binding; _exchange = exchangeAdapter; _queue = queueAdapter; @@ -205,13 +205,6 @@ final class BindingAdapter extends AbstractAdapter implements Binding return super.getAttribute(name); //TODO } - @Override - public Object setAttribute(final String name, final Object expected, final Object desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - return super.setAttribute(name, expected, desired); //TODO - } - @Override public Collection getAttributeNames() { @@ -219,14 +212,14 @@ final class BindingAdapter extends AbstractAdapter implements Binding } @Override - public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, + protected boolean setState(State currentState, State desiredState) throws IllegalStateTransitionException, AccessControlException { if (desiredState == State.DELETED) { delete(); - return State.DELETED; + return true; } - return super.setDesiredState(currentState, desiredState); + return false; } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index f1cce2d45c..533ecfe937 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -21,82 +21,211 @@ package org.apache.qpid.server.model.adapter; import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.security.AccessControlException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; +import java.util.UUID; + +import javax.net.ssl.KeyManagerFactory; + +import org.apache.log4j.Logger; import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.BrokerActor; +import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfigurationChangeListener; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Statistics; -import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry; -import org.apache.qpid.server.transport.QpidAcceptor; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.security.group.FileGroupManager; +import org.apache.qpid.server.security.group.GroupManager; +import org.apache.qpid.server.security.group.GroupPrincipalAccessor; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.util.MapValueConverter; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHostRegistry.RegistryChangeListener, - IApplicationRegistry.PortBindingListener, - IAuthenticationManagerRegistry.RegistryChangeListener +public class BrokerAdapter extends AbstractAdapter implements Broker, ConfigurationChangeListener { - - private final IApplicationRegistry _applicationRegistry; - private String _name; - private final Map _vhostAdapters = - new HashMap(); - private final StatisticsAdapter _statistics; - private final Map _portAdapters = new HashMap(); - private Collection _httpManagementPorts; - - private final Map _authManagerAdapters = - new HashMap(); - - - public BrokerAdapter(final IApplicationRegistry instance) - { - super(UUIDGenerator.generateRandomUUID()); - _applicationRegistry = instance; - _name = "Broker"; - _statistics = new StatisticsAdapter(instance); - - instance.getVirtualHostRegistry().addRegistryChangeListener(this); - populateVhosts(); - instance.addPortBindingListener(this); - populatePorts(); - instance.addRegistryChangeListener(this); - populateAuthenticationManagers(); - } - - private void populateVhosts() - { - synchronized(_vhostAdapters) - { - Collection actualVhosts = - _applicationRegistry.getVirtualHostRegistry().getVirtualHosts(); - for(org.apache.qpid.server.virtualhost.VirtualHost vh : actualVhosts) - { - if(!_vhostAdapters.containsKey(vh)) - { - _vhostAdapters.put(vh, new VirtualHostAdapter(this, vh)); - } - } - + private static final Logger LOGGER = Logger.getLogger(BrokerAdapter.class); + + @SuppressWarnings("serial") + public static final Map> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap>(){{ + put(ALERT_THRESHOLD_MESSAGE_AGE, Long.class); + put(ALERT_THRESHOLD_MESSAGE_COUNT, Long.class); + put(ALERT_THRESHOLD_QUEUE_DEPTH, Long.class); + put(ALERT_THRESHOLD_MESSAGE_SIZE, Long.class); + put(ALERT_REPEAT_GAP, Long.class); + put(FLOW_CONTROL_SIZE_BYTES, Long.class); + put(FLOW_CONTROL_RESUME_SIZE_BYTES, Long.class); + put(HOUSEKEEPING_CHECK_PERIOD, Long.class); + + put(DEAD_LETTER_QUEUE_ENABLED, Boolean.class); + put(STATISTICS_REPORTING_RESET_ENABLED, Boolean.class); + + put(MAXIMUM_DELIVERY_ATTEMPTS, Integer.class); + put(SESSION_COUNT_LIMIT, Integer.class); + put(HEART_BEAT_DELAY, Integer.class); + put(STATISTICS_REPORTING_PERIOD, Integer.class); + + put(ACL_FILE, String.class); + put(NAME, String.class); + put(DEFAULT_VIRTUAL_HOST, String.class); + put(DEFAULT_AUTHENTICATION_PROVIDER, String.class); + + put(KEY_STORE_PATH, String.class); + put(KEY_STORE_PASSWORD, String.class); + put(KEY_STORE_CERT_ALIAS, String.class); + put(TRUST_STORE_PATH, String.class); + put(TRUST_STORE_PASSWORD, String.class); + put(GROUP_FILE, String.class); + }}); + + public static final int DEFAULT_STATISTICS_REPORTING_PERIOD = 0; + public static final boolean DEFAULT_STATISTICS_REPORTING_RESET_ENABLED = false; + public static final long DEFAULT_ALERT_REPEAT_GAP = 30000l; + public static final long DEFAULT_ALERT_THRESHOLD_MESSAGE_AGE = 0l; + public static final long DEFAULT_ALERT_THRESHOLD_MESSAGE_COUNT = 0l; + public static final long DEFAULT_ALERT_THRESHOLD_MESSAGE_SIZE = 0l; + public static final long DEFAULT_ALERT_THRESHOLD_QUEUE_DEPTH = 0l; + public static final boolean DEFAULT_DEAD_LETTER_QUEUE_ENABLED = false; + public static final int DEFAULT_MAXIMUM_DELIVERY_ATTEMPTS = 0; + public static final long DEFAULT_FLOW_CONTROL_RESUME_SIZE_BYTES = 0l; + public static final long DEFAULT_FLOW_CONTROL_SIZE_BYTES = 0l; + public static final long DEFAULT_HOUSEKEEPING_CHECK_PERIOD = 30000l; + public static final int DEFAULT_HEART_BEAT_DELAY = 0; + public static final int DEFAULT_SESSION_COUNT_LIMIT = 256; + public static final String DEFAULT_NAME = "QpidBroker"; + private static final String DEFAULT_KEY_STORE_NAME = "defaultKeyStore"; + private static final String DEFAULT_TRUST_STORE_NAME = "defaultTrustStore"; + private static final String DEFAULT_GROUP_PROFIDER_NAME = "defaultGroupProvider"; + + private static final String DUMMY_PASSWORD_MASK = "********"; + + @SuppressWarnings("serial") + private static final Map DEFAULTS = Collections.unmodifiableMap(new HashMap(){{ + put(Broker.STATISTICS_REPORTING_PERIOD, DEFAULT_STATISTICS_REPORTING_PERIOD); + put(Broker.STATISTICS_REPORTING_RESET_ENABLED, DEFAULT_STATISTICS_REPORTING_RESET_ENABLED); + put(Broker.ALERT_REPEAT_GAP, DEFAULT_ALERT_REPEAT_GAP); + put(Broker.ALERT_THRESHOLD_MESSAGE_AGE, DEFAULT_ALERT_THRESHOLD_MESSAGE_AGE); + put(Broker.ALERT_THRESHOLD_MESSAGE_COUNT, DEFAULT_ALERT_THRESHOLD_MESSAGE_COUNT); + put(Broker.ALERT_THRESHOLD_MESSAGE_SIZE, DEFAULT_ALERT_THRESHOLD_MESSAGE_SIZE); + put(Broker.ALERT_THRESHOLD_QUEUE_DEPTH, DEFAULT_ALERT_THRESHOLD_QUEUE_DEPTH); + put(Broker.DEAD_LETTER_QUEUE_ENABLED, DEFAULT_DEAD_LETTER_QUEUE_ENABLED); + put(Broker.MAXIMUM_DELIVERY_ATTEMPTS, DEFAULT_MAXIMUM_DELIVERY_ATTEMPTS); + put(Broker.FLOW_CONTROL_RESUME_SIZE_BYTES, DEFAULT_FLOW_CONTROL_RESUME_SIZE_BYTES); + put(Broker.FLOW_CONTROL_SIZE_BYTES, DEFAULT_FLOW_CONTROL_SIZE_BYTES); + put(Broker.HOUSEKEEPING_CHECK_PERIOD, DEFAULT_HOUSEKEEPING_CHECK_PERIOD); + put(Broker.HEART_BEAT_DELAY, DEFAULT_HEART_BEAT_DELAY); + put(Broker.SESSION_COUNT_LIMIT, DEFAULT_SESSION_COUNT_LIMIT); + put(Broker.NAME, DEFAULT_NAME); + }}); + + + + + private final StatisticsGatherer _statisticsGatherer; + private final VirtualHostRegistry _virtualHostRegistry; + private final LogRecorder _logRecorder; + private final RootMessageLogger _rootMessageLogger; + private StatisticsAdapter _statistics; + + private final Map _vhostAdapters = new HashMap(); + private final Map _portAdapters = new HashMap(); + private final Map _authenticationProviders = new HashMap(); + private final Map _groupProviders = new HashMap(); + private final Map _plugins = new HashMap(); + private final Map _keyStores = new HashMap(); + private final Map _trustStores = new HashMap(); + + private final AuthenticationProviderFactory _authenticationProviderFactory; + private AuthenticationProvider _defaultAuthenticationProvider; + + private final PortFactory _portFactory; + private final SecurityManager _securityManager; + private final UUID _defaultKeyStoreId; + private final UUID _defaultTrustStoreId; + + public BrokerAdapter(UUID id, Map attributes, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, + LogRecorder logRecorder, RootMessageLogger rootMessageLogger, AuthenticationProviderFactory authenticationProviderFactory, + PortFactory portFactory, TaskExecutor taskExecutor) + { + super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); + _statisticsGatherer = statisticsGatherer; + _virtualHostRegistry = virtualHostRegistry; + _logRecorder = logRecorder; + _rootMessageLogger = rootMessageLogger; + _statistics = new StatisticsAdapter(statisticsGatherer); + _authenticationProviderFactory = authenticationProviderFactory; + _portFactory = portFactory; + _securityManager = new SecurityManager((String)getAttribute(ACL_FILE)); + + _defaultKeyStoreId = UUIDGenerator.generateBrokerChildUUID(KeyStore.class.getSimpleName(), DEFAULT_KEY_STORE_NAME); + _defaultTrustStoreId = UUIDGenerator.generateBrokerChildUUID(TrustStore.class.getSimpleName(), DEFAULT_TRUST_STORE_NAME); + createBrokerChildrenFromAttributes(); + } + + /* + * A temporary method to create broker children that can be only configured via broker attributes + */ + private void createBrokerChildrenFromAttributes() + { + String groupFile = (String) getAttribute(GROUP_FILE); + if (groupFile != null) + { + GroupManager groupManager = new FileGroupManager(groupFile); + UUID groupProviderId = UUIDGenerator.generateBrokerChildUUID(GroupProvider.class.getSimpleName(), + DEFAULT_GROUP_PROFIDER_NAME); + GroupProviderAdapter groupProviderAdapter = new GroupProviderAdapter(groupProviderId, groupManager, this); + addGroupProvider(groupProviderAdapter); + } + Map actualAttributes = getActualAttributes(); + String keyStorePath = (String) getAttribute(KEY_STORE_PATH); + if (keyStorePath != null) + { + Map keyStoreAttributes = new HashMap(); + keyStoreAttributes.put(KeyStore.NAME, DEFAULT_KEY_STORE_NAME); + keyStoreAttributes.put(KeyStore.PATH, keyStorePath); + keyStoreAttributes.put(KeyStore.PASSWORD, (String) actualAttributes.get(KEY_STORE_PASSWORD)); + keyStoreAttributes.put(KeyStore.TYPE, java.security.KeyStore.getDefaultType()); + keyStoreAttributes.put(KeyStore.CERTIFICATE_ALIAS, getAttribute(KEY_STORE_CERT_ALIAS)); + keyStoreAttributes.put(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM, KeyManagerFactory.getDefaultAlgorithm()); + KeyStoreAdapter KeyStoreAdapter = new KeyStoreAdapter(_defaultKeyStoreId, this, keyStoreAttributes); + addKeyStore(KeyStoreAdapter); + } + String trustStorePath = (String) getAttribute(TRUST_STORE_PATH); + if (trustStorePath != null) + { + Map trsustStoreAttributes = new HashMap(); + trsustStoreAttributes.put(TrustStore.NAME, DEFAULT_TRUST_STORE_NAME); + trsustStoreAttributes.put(TrustStore.PATH, trustStorePath); + trsustStoreAttributes.put(TrustStore.PASSWORD, (String) actualAttributes.get(TRUST_STORE_PASSWORD)); + trsustStoreAttributes.put(TrustStore.TYPE, java.security.KeyStore.getDefaultType()); + trsustStoreAttributes.put(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, KeyManagerFactory.getDefaultAlgorithm()); + TrustStoreAdapter trustStore = new TrustStoreAdapter(_defaultTrustStoreId, this, trsustStoreAttributes); + addTrustStore(trustStore); } } - public Collection getVirtualHosts() { synchronized(_vhostAdapters) @@ -105,81 +234,57 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHos } } - private void populatePorts() + + public Collection getPorts() { synchronized (_portAdapters) { - Map acceptors = _applicationRegistry.getAcceptors(); - - for(Map.Entry entry : acceptors.entrySet()) - { - if(!_portAdapters.containsKey(entry.getValue())) - { - _portAdapters.put(entry.getValue(), new PortAdapter(this, entry.getValue(), entry.getKey())); - } - } - if(_applicationRegistry.useHTTPManagement() || _applicationRegistry.useHTTPSManagement()) - { - ArrayList httpPorts = new ArrayList(); - if (_applicationRegistry.useHTTPManagement()) - { - httpPorts.add(new HTTPPortAdapter(this, _applicationRegistry.getHTTPManagementPort())); - } - if (_applicationRegistry.useHTTPSManagement()) - { - httpPorts.add(new HTTPPortAdapter(this, _applicationRegistry.getHTTPSManagementPort(), Protocol.HTTPS, Transport.SSL)); - } - _httpManagementPorts = Collections.unmodifiableCollection(httpPorts); - } + final ArrayList ports = new ArrayList(_portAdapters.values()); + return ports; } } - public Collection getPorts() + public Collection getAuthenticationProviders() { - synchronized (_portAdapters) + synchronized (_authenticationProviders) { - final ArrayList ports = new ArrayList(_portAdapters.values()); - if(_httpManagementPorts != null) - { - ports.addAll(_httpManagementPorts); - } - return ports; + return new ArrayList(_authenticationProviders.values()); } } - private void populateAuthenticationManagers() + public AuthenticationProvider getAuthenticationProviderByName(String authenticationProviderName) { - synchronized (_authManagerAdapters) + Collection providers = getAuthenticationProviders(); + for (AuthenticationProvider authenticationProvider : providers) { - IAuthenticationManagerRegistry authenticationManagerRegistry = - _applicationRegistry.getAuthenticationManagerRegistry(); - if(authenticationManagerRegistry != null) + if (authenticationProvider.getName().equals(authenticationProviderName)) { - Map authenticationManagers = - authenticationManagerRegistry.getAvailableAuthenticationManagers(); - - for(Map.Entry entry : authenticationManagers.entrySet()) - { - if(!_authManagerAdapters.containsKey(entry.getValue())) - { - _authManagerAdapters.put(entry.getValue(), - AuthenticationProviderAdapter.createAuthenticationProviderAdapter(this, - entry.getValue())); - } - } + return authenticationProvider; } } + return null; } - public Collection getAuthenticationProviders() + @Override + public AuthenticationProvider getDefaultAuthenticationProvider() + { + return _defaultAuthenticationProvider; + } + + public void setDefaultAuthenticationProvider(AuthenticationProvider provider) + { + _defaultAuthenticationProvider = provider; + } + + @Override + public Collection getGroupProviders() { - synchronized (_authManagerAdapters) + synchronized (_groupProviders) { - final ArrayList authManagers = - new ArrayList(_authManagerAdapters.values()); - return authManagers; + final ArrayList groupManagers = + new ArrayList(_groupProviders.values()); + return groupManagers; } - } public VirtualHost createVirtualHost(final String name, @@ -193,22 +298,29 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHos return null; //TODO } - public VirtualHost createVirtualHost(final Map attributes) + private VirtualHost createVirtualHost(final Map attributes) throws AccessControlException, IllegalArgumentException { - return null; //TODO + final VirtualHostAdapter virtualHostAdapter = new VirtualHostAdapter(UUID.randomUUID(), attributes, this, + _statisticsGatherer, getTaskExecutor()); + addVirtualHost(virtualHostAdapter); + virtualHostAdapter.setDesiredState(State.INITIALISING, State.ACTIVE); + return virtualHostAdapter; } - public void deleteVirtualHost(final VirtualHost vhost) - throws AccessControlException, IllegalStateException + private boolean deleteVirtualHost(final VirtualHost vhost) throws AccessControlException, IllegalStateException { - //TODO - throw new UnsupportedOperationException("Not yet implemented"); + synchronized (_vhostAdapters) + { + _vhostAdapters.remove(vhost); + } + vhost.removeChangeListener(this); + return true; } public String getName() { - return _name; + return (String)getAttribute(NAME); } public String setName(final String currentName, final String desiredName) @@ -262,6 +374,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHos return _statistics; } + @SuppressWarnings("unchecked") @Override public Collection getChildren(Class clazz) { @@ -277,12 +390,30 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHos { return (Collection) getAuthenticationProviders(); } + else if(clazz == GroupProvider.class) + { + return (Collection) getGroupProviders(); + } + else if(clazz == KeyStore.class) + { + return (Collection) getKeyStores(); + } + else if(clazz == TrustStore.class) + { + return (Collection) getTrustStores(); + } + else if(clazz == Plugin.class) + { + return (Collection) getPlugins(); + } return Collections.emptySet(); } + //TODO: ACL + @SuppressWarnings("unchecked") @Override - public C createChild(Class childClass, Map attributes, ConfiguredObject... otherParents) + public C addChild(Class childClass, Map attributes, ConfiguredObject... otherParents) { if(childClass == VirtualHost.class) { @@ -302,111 +433,107 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHos } } - private Port createPort(Map attributes) + private void addPort(Port port) { - // TODO - return null; + synchronized (_portAdapters) + { + int portNumber = port.getPort(); + if(_portAdapters.containsKey(portNumber)) + { + throw new IllegalArgumentException("Cannot add port " + port + " because port number " + portNumber + " already configured"); + } + _portAdapters.put(portNumber, port); + } + port.addChangeListener(this); } - private AuthenticationProvider createAuthenticationProvider(Map attributes) + private Port createPort(Map attributes) { - // TODO - return null; + Port port = _portFactory.createPort(UUID.randomUUID(), this, attributes); + addPort(port); + return port; } + private AuthenticationProvider createAuthenticationProvider(Map attributes) + { + // it's cheap to create the groupPrincipalAccessor on the fly + GroupPrincipalAccessor groupPrincipalAccessor = new GroupPrincipalAccessor(_groupProviders.values()); + + AuthenticationProvider authenticationProvider = _authenticationProviderFactory.create(UUID.randomUUID(), this, attributes, groupPrincipalAccessor); + addAuthenticationProvider(authenticationProvider); + return authenticationProvider; + } - public void virtualHostRegistered(org.apache.qpid.server.virtualhost.VirtualHost virtualHost) + /** + * @throws IllegalConfigurationException if an AuthenticationProvider with the same name already exists + */ + private void addAuthenticationProvider(AuthenticationProvider authenticationProvider) { - VirtualHostAdapter adapter = null; - synchronized (_vhostAdapters) + String name = authenticationProvider.getName(); + synchronized (_authenticationProviders) { - if(!_vhostAdapters.containsKey(virtualHost)) + if(_authenticationProviders.containsKey(name)) { - adapter = new VirtualHostAdapter(this, virtualHost); - _vhostAdapters.put(virtualHost, adapter); + throw new IllegalConfigurationException("Cannot add AuthenticationProvider because one with name " + name + " already exists"); } + _authenticationProviders.put(name, authenticationProvider); } - if(adapter != null) - { - childAdded(adapter); - } + authenticationProvider.addChangeListener(this); } - public void virtualHostUnregistered(org.apache.qpid.server.virtualhost.VirtualHost virtualHost) + private void addGroupProvider(GroupProvider groupProvider) { - VirtualHostAdapter adapter = null; - - synchronized (_vhostAdapters) - { - adapter = _vhostAdapters.remove(virtualHost); - } - if(adapter != null) + synchronized (_groupProviders) { - childRemoved(adapter); + String name = groupProvider.getName(); + if(_groupProviders.containsKey(name)) + { + throw new IllegalConfigurationException("Cannot add GroupProvider because one with name " + name + " already exists"); + } + _groupProviders.put(name, groupProvider); } + groupProvider.addChangeListener(this); } - @Override - public void authenticationManagerRegistered(AuthenticationManager authenticationManager) + private boolean deleteGroupProvider(GroupProvider object) + { + throw new UnsupportedOperationException("Not implemented yet!"); + } + + private void addKeyStore(KeyStore keyStore) { - AuthenticationProviderAdapter adapter = null; - synchronized (_authManagerAdapters) + synchronized (_keyStores) { - if(!_authManagerAdapters.containsKey(authenticationManager)) + if(_keyStores.containsKey(keyStore.getId())) { - adapter = - AuthenticationProviderAdapter.createAuthenticationProviderAdapter(this, authenticationManager); - _authManagerAdapters.put(authenticationManager, adapter); + throw new IllegalConfigurationException("Cannot add KeyStore because one with id " + keyStore.getId() + " already exists"); } + _keyStores.put(keyStore.getId(), keyStore); } - if(adapter != null) - { - childAdded(adapter); - } + keyStore.addChangeListener(this); } - @Override - public void authenticationManagerUnregistered(AuthenticationManager authenticationManager) + private boolean deleteKeyStore(KeyStore object) { - AuthenticationProviderAdapter adapter; - synchronized (_authManagerAdapters) - { - adapter = _authManagerAdapters.remove(authenticationManager); - } - if(adapter != null) - { - childRemoved(adapter); - } + throw new UnsupportedOperationException("Not implemented yet!"); } - - @Override - public void bound(QpidAcceptor acceptor, InetSocketAddress bindAddress) + private void addTrustStore(TrustStore trustStore) { - synchronized (_portAdapters) + synchronized (_trustStores) { - if(!_portAdapters.containsKey(acceptor)) + if(_trustStores.containsKey(trustStore.getId())) { - PortAdapter adapter = new PortAdapter(this, acceptor, bindAddress); - _portAdapters.put(acceptor, adapter); - childAdded(adapter); + throw new IllegalConfigurationException("Cannot add TrustStore because one with id " + trustStore.getId() + " already exists"); } + _trustStores.put(trustStore.getId(), trustStore); } + trustStore.addChangeListener(this); } - @Override - public void unbound(QpidAcceptor acceptor) + private boolean deleteTrustStore(TrustStore object) { - PortAdapter adapter = null; - - synchronized (_portAdapters) - { - adapter = _portAdapters.remove(acceptor); - } - if(adapter != null) - { - childRemoved(adapter); - } + throw new UnsupportedOperationException("Not implemented yet!"); } @Override @@ -422,10 +549,6 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHos { return getId(); } - else if(NAME.equals(name)) - { - return getName(); - } else if(STATE.equals(name)) { return State.ACTIVE; @@ -481,14 +604,316 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHos { // TODO } + else if (DEFAULT_AUTHENTICATION_PROVIDER.equals(name)) + { + return _defaultAuthenticationProvider == null ? null : _defaultAuthenticationProvider.getName(); + } + else if (KEY_STORE_PASSWORD.equals(name)) + { + return DUMMY_PASSWORD_MASK; + } + else if (TRUST_STORE_PASSWORD.equals(name)) + { + return DUMMY_PASSWORD_MASK; + } + return super.getAttribute(name); + } - return super.getAttribute(name); //TODO - Implement. + private boolean deletePort(Port portAdapter) + { + Port removedPort = null; + synchronized (_portAdapters) + { + removedPort = _portAdapters.remove(portAdapter.getPort()); + } + return removedPort != null; + } + + private boolean deleteAuthenticationProvider(AuthenticationProvider authenticationProvider) + { + AuthenticationProvider removedAuthenticationProvider = null; + synchronized (_authenticationProviders) + { + removedAuthenticationProvider = _authenticationProviders.remove(authenticationProvider.getName()); + } + return removedAuthenticationProvider != null; + } + + private void addVirtualHost(VirtualHost virtualHost) + { + synchronized (_vhostAdapters) + { + String name = virtualHost.getName(); + if (_vhostAdapters.containsKey(name)) + { + throw new IllegalConfigurationException("Virtual host with name " + name + " is already specified!"); + } + _vhostAdapters.put(name, virtualHost); + } + virtualHost.addChangeListener(this); } @Override - public Object setAttribute(String name, Object expected, Object desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException + public boolean setState(State currentState, State desiredState) + { + if (desiredState == State.ACTIVE) + { + changeState(_groupProviders, currentState, State.ACTIVE, false); + changeState(_authenticationProviders, currentState, State.ACTIVE, false); + + CurrentActor.set(new BrokerActor(getRootMessageLogger())); + try + { + changeState(_vhostAdapters, currentState, State.ACTIVE, false); + } + finally + { + CurrentActor.remove(); + } + + changeState(_portAdapters, currentState,State.ACTIVE, false); + changeState(_plugins, currentState,State.ACTIVE, false); + return true; + } + else if (desiredState == State.STOPPED) + { + changeState(_plugins, currentState,State.STOPPED, true); + changeState(_portAdapters, currentState, State.STOPPED, true); + changeState(_vhostAdapters,currentState, State.STOPPED, true); + changeState(_authenticationProviders, currentState, State.STOPPED, true); + changeState(_groupProviders, currentState, State.STOPPED, true); + return true; + } + return false; + } + + private void changeState(Map configuredObjectMap, State currentState, State desiredState, boolean swallowException) + { + synchronized(configuredObjectMap) + { + Collection adapters = configuredObjectMap.values(); + for (ConfiguredObject configuredObject : adapters) + { + if (State.ACTIVE.equals(desiredState) && State.QUIESCED.equals(configuredObject.getActualState())) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(configuredObject + " cannot be activated as it is " +State.QUIESCED); + } + continue; + } + try + { + configuredObject.setDesiredState(currentState, desiredState); + } + catch(RuntimeException e) + { + if (swallowException) + { + LOGGER.error("Failed to stop " + configuredObject, e); + } + else + { + throw e; + } + } + } + } + } + + @Override + public void stateChanged(ConfiguredObject object, State oldState, State newState) + { + if(newState == State.DELETED) + { + boolean childDeleted = false; + if(object instanceof AuthenticationProvider) + { + childDeleted = deleteAuthenticationProvider((AuthenticationProvider)object); + } + else if(object instanceof Port) + { + childDeleted = deletePort((Port)object); + } + else if(object instanceof VirtualHost) + { + childDeleted = deleteVirtualHost((VirtualHost)object); + } + else if(object instanceof GroupProvider) + { + childDeleted = deleteGroupProvider((GroupProvider)object); + } + else if(object instanceof KeyStore) + { + childDeleted = deleteKeyStore((KeyStore)object); + } + else if(object instanceof TrustStore) + { + childDeleted = deleteTrustStore((TrustStore)object); + } + if(childDeleted) + { + childRemoved(object); + } + } + } + + @Override + public void childAdded(ConfiguredObject object, ConfiguredObject child) + { + // no-op + } + + @Override + public void childRemoved(ConfiguredObject object, ConfiguredObject child) + { + // no-op + } + + @Override + public void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue) + { + // no-op + } + + private void addPlugin(ConfiguredObject plugin) + { + synchronized(_plugins) + { + if (_plugins.containsKey(plugin.getId())) + { + throw new IllegalConfigurationException("Plugin with id '" + plugin.getId() + "' is already registered!"); + } + _plugins.put(plugin.getId(), plugin); + } + plugin.addChangeListener(this); + } + + + private Collection getPlugins() + { + synchronized(_plugins) + { + return Collections.unmodifiableCollection(_plugins.values()); + } + } + + public void recoverChild(ConfiguredObject object) + { + if(object instanceof AuthenticationProvider) + { + addAuthenticationProvider((AuthenticationProvider)object); + } + else if(object instanceof Port) + { + addPort((Port)object); + } + else if(object instanceof VirtualHost) + { + addVirtualHost((VirtualHost)object); + } + else if(object instanceof GroupProvider) + { + addGroupProvider((GroupProvider)object); + } + else if(object instanceof KeyStore) + { + addKeyStore((KeyStore)object); + } + else if(object instanceof TrustStore) + { + addTrustStore((TrustStore)object); + } + else if(object instanceof Plugin) + { + addPlugin(object); + } + else + { + throw new IllegalArgumentException("Attempted to recover unexpected type of configured object: " + object.getClass().getName()); + } + } + + @Override + public RootMessageLogger getRootMessageLogger() + { + return _rootMessageLogger; + } + + @Override + public SecurityManager getSecurityManager() + { + return _securityManager; + } + + @Override + public LogRecorder getLogRecorder() + { + return _logRecorder; + } + + @Override + public VirtualHost findVirtualHostByName(String name) + { + return _vhostAdapters.get(name); + } + + @Override + public SubjectCreator getSubjectCreator(SocketAddress localAddress) + { + InetSocketAddress inetSocketAddress = (InetSocketAddress)localAddress; + AuthenticationProvider provider = _defaultAuthenticationProvider; + Collection ports = getPorts(); + for (Port p : ports) + { + if (inetSocketAddress.getPort() == p.getPort()) + { + provider = p.getAuthenticationProvider(); + break; + } + } + return provider.getSubjectCreator(); + } + + @Override + public Collection getKeyStores() + { + synchronized(_trustStores) + { + return Collections.unmodifiableCollection(_keyStores.values()); + } + } + + @Override + public Collection getTrustStores() + { + synchronized(_trustStores) + { + return Collections.unmodifiableCollection(_trustStores.values()); + } + } + + @Override + public VirtualHostRegistry getVirtualHostRegistry() + { + return _virtualHostRegistry; + } + + @Override + public KeyStore getDefaultKeyStore() + { + return _keyStores.get(_defaultKeyStoreId); + } + + @Override + public TrustStore getDefaultTrustStore() + { + return _trustStores.get(_defaultTrustStoreId); + } + + @Override + public TaskExecutor getTaskExecutor() { - return super.setAttribute(name, expected, desired); //TODO - Implement. + return super.getTaskExecutor(); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java index 5439f6a560..84f99e1f17 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java @@ -38,6 +38,7 @@ import org.apache.qpid.server.model.Session; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.stats.StatisticsGatherer; @@ -50,9 +51,9 @@ final class ConnectionAdapter extends AbstractAdapter implements Connection new HashMap(); private final Statistics _statistics; - public ConnectionAdapter(final AMQConnectionModel conn) + public ConnectionAdapter(final AMQConnectionModel conn, TaskExecutor taskExecutor) { - super(UUIDGenerator.generateRandomUUID()); + super(UUIDGenerator.generateRandomUUID(), taskExecutor); _connection = conn; _statistics = new ConnectionStatisticsAdapter(conn); } @@ -74,7 +75,7 @@ final class ConnectionAdapter extends AbstractAdapter implements Connection { if(!_sessionAdapters.containsKey(session)) { - _sessionAdapters.put(session, new SessionAdapter(session)); + _sessionAdapters.put(session, new SessionAdapter(session, getTaskExecutor())); } } return new ArrayList(_sessionAdapters.values()); @@ -198,52 +199,6 @@ final class ConnectionAdapter extends AbstractAdapter implements Connection return super.getAttribute(name); } - @Override - public Object setAttribute(String name, Object expected, Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException - { - if(name.equals(CLIENT_ID)) - { - - } - else if(name.equals(CLIENT_VERSION)) - { - - } - else if(name.equals(INCOMING)) - { - - } - else if(name.equals(LOCAL_ADDRESS)) - { - - } - else if(name.equals(PRINCIPAL)) - { - - } - else if(name.equals(PROPERTIES)) - { - - } - else if(name.equals(REMOTE_ADDRESS)) - { - - } - else if(name.equals(REMOTE_PROCESS_NAME)) - { - - } - else if(name.equals(REMOTE_PROCESS_PID)) - { - - } - else if(name.equals(SESSION_COUNT_LIMIT)) - { - - } - return super.setAttribute(name, expected, desired); - } - @Override public Collection getAttributeNames() { @@ -270,7 +225,8 @@ final class ConnectionAdapter extends AbstractAdapter implements Connection } } - public C createChild(Class childClass, Map attributes, ConfiguredObject... otherParents) + @Override + public C addChild(Class childClass, Map attributes, ConfiguredObject... otherParents) { if(childClass == Session.class) { @@ -310,4 +266,11 @@ final class ConnectionAdapter extends AbstractAdapter implements Connection return super.getStatistic(name); } } + + @Override + protected boolean setState(State currentState, State desiredState) + { + // TODO: add state management + return false; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java index 031d518670..e6d3fab2f8 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java @@ -45,7 +45,7 @@ public class ConsumerAdapter extends AbstractAdapter implements Consumer queueAdapter.getName(), subscription.getSessionModel().getConnectionModel().getRemoteAddressString(), String.valueOf(subscription.getSessionModel().getChannelId()), - subscription.getConsumerName())); + subscription.getConsumerName()), queueAdapter.getTaskExecutor()); _subscription = subscription; _queue = queueAdapter; _statistics = new ConsumerStatistics(); @@ -107,13 +107,6 @@ public class ConsumerAdapter extends AbstractAdapter implements Consumer return Consumer.AVAILABLE_ATTRIBUTES; } - @Override - public Object setAttribute(final String name, final Object expected, final Object desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - return super.setAttribute(name, expected, desired); //TODO - } - @Override public Object getAttribute(final String name) { @@ -222,4 +215,11 @@ public class ConsumerAdapter extends AbstractAdapter implements Consumer return null; // TODO - Implement } } + + @Override + protected boolean setState(State currentState, State desiredState) + { + // TODO : Add state management + return false; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java index df0f29fbc3..5d5f3f7378 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java @@ -33,16 +33,15 @@ import org.apache.qpid.AMQSecurityException; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.exchange.ExchangeType; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.IllegalStateTransitionException; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Publisher; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.util.MapValueConverter; import org.apache.qpid.server.virtualhost.VirtualHost; final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apache.qpid.server.exchange.Exchange.BindingListener @@ -57,7 +56,7 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa public ExchangeAdapter(final VirtualHostAdapter virtualHostAdapter, final org.apache.qpid.server.exchange.Exchange exchange) { - super(exchange.getId()); + super(exchange.getId(), virtualHostAdapter.getTaskExecutor()); _statistics = new ExchangeStatistics(); _vhost = virtualHostAdapter; _exchange = exchange; @@ -113,8 +112,8 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa throws AccessControlException, IllegalStateException { attributes = new HashMap(attributes); - String bindingKey = getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, ""); - Map bindingArgs = getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.EMPTY_MAP); + String bindingKey = MapValueConverter.getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, ""); + Map bindingArgs = MapValueConverter.getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.emptyMap()); attributes.remove(org.apache.qpid.server.model.Binding.NAME); attributes.remove(org.apache.qpid.server.model.Binding.ARGUMENTS); @@ -257,7 +256,7 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa } @Override - public C createChild(Class childClass, Map attributes, ConfiguredObject... otherParents) + public C addChild(Class childClass, Map attributes, ConfiguredObject... otherParents) { if(childClass == org.apache.qpid.server.model.Binding.class) { @@ -368,13 +367,6 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa return super.getAttribute(name); } - @Override - public Object setAttribute(String name, Object expected, Object desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - return super.setAttribute(name, expected, desired); //TODO - Implement - } - @Override public Collection getAttributeNames() { @@ -382,15 +374,14 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa } @Override - public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, - AccessControlException + protected boolean setState(State currentState, State desiredState) { if (desiredState == State.DELETED) { delete(); - return State.DELETED; + return true; } - return super.setDesiredState(currentState, desiredState); + return false; } private class ExchangeStatistics implements Statistics diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java new file mode 100644 index 0000000000..0fa834bc28 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/GroupProviderAdapter.java @@ -0,0 +1,550 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Group; +import org.apache.qpid.server.model.GroupMember; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.IllegalStateTransitionException; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.group.GroupManager; +import org.apache.qpid.server.security.SecurityManager; + +public class GroupProviderAdapter extends AbstractAdapter implements + GroupProvider +{ + private final GroupManager _groupManager; + private final Broker _broker; + public GroupProviderAdapter(UUID id, GroupManager groupManager, Broker broker) + { + super(id, broker.getTaskExecutor()); + + if (groupManager == null) + { + throw new IllegalArgumentException("GroupManager must not be null"); + } + _groupManager = groupManager; + _broker = broker; + addParent(Broker.class, broker); + } + + @Override + public String getName() + { + return _groupManager.getClass().getSimpleName(); + } + + @Override + public String setName(String currentName, String desiredName) + throws IllegalStateException, AccessControlException + { + return null; + } + + @Override + public State getActualState() + { + return null; + } + + @Override + public boolean isDurable() + { + return true; + } + + @Override + public void setDurable(boolean durable) throws IllegalStateException, + AccessControlException, IllegalArgumentException + { + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, + LifetimePolicy desired) throws IllegalStateException, + AccessControlException, IllegalArgumentException + { + return null; + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) + throws IllegalStateException, AccessControlException, + IllegalArgumentException + { + return 0; + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public Collection getAttributeNames() + { + return GroupProvider.AVAILABLE_ATTRIBUTES; + } + + @Override + public Object getAttribute(String name) + { + if (TYPE.equals(name)) + { + return getName(); + } + else if (CREATED.equals(name)) + { + // TODO + } + else if (DURABLE.equals(name)) + { + return true; + } + else if (ID.equals(name)) + { + return getId(); + } + else if (LIFETIME_POLICY.equals(name)) + { + return LifetimePolicy.PERMANENT; + } + else if (NAME.equals(name)) + { + return getName(); + } + else if (STATE.equals(name)) + { + return State.ACTIVE; // TODO + } + else if (TIME_TO_LIVE.equals(name)) + { + // TODO + } + else if (UPDATED.equals(name)) + { + // TODO + } + return super.getAttribute(name); + } + + @Override + public C addChild(Class childClass, + Map attributes, ConfiguredObject... otherParents) + { + if (childClass == Group.class) + { + String groupName = (String) attributes.get(Group.NAME); + + if (getSecurityManager().authoriseGroupOperation(Operation.CREATE, groupName)) + { + _groupManager.createGroup(groupName); + return (C) new GroupAdapter(groupName, getTaskExecutor()); + } + else + { + throw new AccessControlException("Do not have permission" + + " to create new group"); + } + } + + throw new IllegalArgumentException( + "This group provider does not support creating children of type: " + + childClass); + } + + @SuppressWarnings("unchecked") + @Override + public Collection getChildren(Class clazz) + { + if (clazz == Group.class) + { + Set groups = _groupManager.getGroupPrincipals(); + Collection principals = new ArrayList(groups.size()); + for (Principal group : groups) + { + principals.add(new GroupAdapter(group.getName(), getTaskExecutor())); + } + return (Collection) Collections + .unmodifiableCollection(principals); + } + else + { + return null; + } + } + + private SecurityManager getSecurityManager() + { + return _broker.getSecurityManager(); + } + + private class GroupAdapter extends AbstractAdapter implements Group + { + private final String _group; + + public GroupAdapter(String group, TaskExecutor taskExecutor) + { + super(UUIDGenerator.generateGroupUUID(GroupProviderAdapter.this.getName(), group), taskExecutor); + _group = group; + + } + + @Override + public String getName() + { + return _group; + } + + @Override + public String setName(String currentName, String desiredName) + throws IllegalStateException, AccessControlException + { + throw new IllegalStateException("Names cannot be updated"); + } + + @Override + public State getActualState() + { + return State.ACTIVE; + } + + @Override + public boolean isDurable() + { + return true; + } + + @Override + public void setDurable(boolean durable) throws IllegalStateException, + AccessControlException, IllegalArgumentException + { + throw new IllegalStateException("Durability cannot be updated"); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, + LifetimePolicy desired) throws IllegalStateException, + AccessControlException, IllegalArgumentException + { + throw new IllegalStateException("LifetimePolicy cannot be updated"); + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) + throws IllegalStateException, AccessControlException, + IllegalArgumentException + { + throw new IllegalStateException("ttl cannot be updated"); + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public Collection getChildren( + Class clazz) + { + if (clazz == GroupMember.class) + { + Set usersInGroup = _groupManager + .getUserPrincipalsForGroup(_group); + Collection members = new ArrayList(); + for (Principal principal : usersInGroup) + { + members.add(new GroupMemberAdapter(principal.getName(), getTaskExecutor())); + } + return (Collection) Collections + .unmodifiableCollection(members); + } + else + { + return null; + } + + } + + @Override + public C addChild(Class childClass, + Map attributes, + ConfiguredObject... otherParents) + { + if (childClass == GroupMember.class) + { + String memberName = (String) attributes.get(GroupMember.NAME); + + if (getSecurityManager().authoriseGroupOperation(Operation.UPDATE, _group)) + { + _groupManager.addUserToGroup(memberName, _group); + return (C) new GroupMemberAdapter(memberName, getTaskExecutor()); + } + else + { + throw new AccessControlException("Do not have permission" + + " to add new group member"); + } + } + + throw new IllegalArgumentException( + "This group provider does not support creating children of type: " + + childClass); + } + + @Override + public Collection getAttributeNames() + { + return Group.AVAILABLE_ATTRIBUTES; + } + + @Override + public Object getAttribute(String name) + { + if (ID.equals(name)) + { + return getId(); + } + else if (NAME.equals(name)) + { + return getName(); + } + return super.getAttribute(name); + } + + @Override + protected boolean setState(State currentState, State desiredState) + throws IllegalStateTransitionException, AccessControlException + { + if (desiredState == State.DELETED) + { + if (getSecurityManager().authoriseGroupOperation(Operation.DELETE, _group)) + { + _groupManager.removeGroup(_group); + return true; + } + else + { + throw new AccessControlException("Do not have permission to delete group"); + } + } + + return false; + } + + private class GroupMemberAdapter extends AbstractAdapter implements + GroupMember + { + private String _memberName; + + public GroupMemberAdapter(String memberName, TaskExecutor taskExecutor) + { + super(UUIDGenerator.generateGroupMemberUUID(GroupProviderAdapter.this.getName(), _group, memberName), taskExecutor); + _memberName = memberName; + } + + @Override + public Collection getAttributeNames() + { + return GroupMember.AVAILABLE_ATTRIBUTES; + } + + @Override + public Object getAttribute(String name) + { + if (ID.equals(name)) + { + return getId(); + } + else if (NAME.equals(name)) + { + return getName(); + } + return super.getAttribute(name); + } + + @Override + public String getName() + { + return _memberName; + } + + @Override + public String setName(String currentName, String desiredName) + throws IllegalStateException, AccessControlException + { + return null; + } + + @Override + public State getActualState() + { + return null; + } + + @Override + public boolean isDurable() + { + return false; + } + + @Override + public void setDurable(boolean durable) + throws IllegalStateException, AccessControlException, + IllegalArgumentException + { + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return null; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, + LifetimePolicy desired) throws IllegalStateException, + AccessControlException, IllegalArgumentException + { + return null; + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) + throws IllegalStateException, AccessControlException, + IllegalArgumentException + { + return 0; + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public Collection getChildren( + Class clazz) + { + return null; + } + + @Override + public C createChild( + Class childClass, Map attributes, + ConfiguredObject... otherParents) + { + return null; + } + + @Override + protected boolean setState(State currentState, State desiredState) + throws IllegalStateTransitionException, + AccessControlException + { + if (desiredState == State.DELETED) + { + if (getSecurityManager().authoriseGroupOperation(Operation.UPDATE, _group)) + { + _groupManager.removeUserFromGroup(_memberName, _group); + return true; + } + else + { + throw new AccessControlException("Do not have permission to remove group member"); + } + } + return false; + } + + } + } + + @Override + protected boolean setState(State currentState, State desiredState) + { + if (desiredState == State.ACTIVE) + { + return true; + } + else if (desiredState == State.STOPPED) + { + return true; + } + // TODO: DELETE state is ignored for now + // in case if we need to delete group provider, then we need AuthenticationProvider to be a change listener of it + // in order to remove deleted group provider from its group provider list + return false; + } + + public Set getGroupPrincipalsForUser(String username) + { + return _groupManager.getGroupPrincipalsForUser(username); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java deleted file mode 100644 index 823d27160b..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java +++ /dev/null @@ -1,273 +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.model.adapter; - -import java.security.AccessControlException; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.Connection; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.Port; -import org.apache.qpid.server.model.Protocol; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.Statistics; -import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.model.VirtualHostAlias; - -public class HTTPPortAdapter extends AbstractAdapter implements Port -{ - private final BrokerAdapter _broker; - private final int _port; - private final Protocol _protocol; - private final Transport _transport; - - public HTTPPortAdapter(BrokerAdapter brokerAdapter, int port) - { - this(brokerAdapter, port, Protocol.HTTP, Transport.TCP); - } - - public HTTPPortAdapter(BrokerAdapter brokerAdapter, int port, Protocol protocol, Transport transport) - { - super(UUIDGenerator.generateRandomUUID()); - _broker = brokerAdapter; - _port = port; - _protocol = protocol; - _transport = transport; - } - - @Override - public String getBindingAddress() - { - return "0.0.0.0"; - } - - @Override - public int getPort() - { - return _port; - } - - @Override - public Collection getTransports() - { - return Collections.singleton(_transport); - } - - @Override - public void addTransport(Transport transport) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - throw new IllegalStateException(); // TODO - Implement - } - - @Override - public Transport removeTransport(Transport transport) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - throw new IllegalStateException(); // TODO - Implement - } - - @Override - public Collection getProtocols() - { - return Collections.singleton(_protocol); - } - - @Override - public void addProtocol(Protocol protocol) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - throw new IllegalStateException(); // TODO - Implement - } - - @Override - public Protocol removeProtocol(Protocol protocol) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - throw new IllegalStateException(); // TODO - Implement - } - - @Override - public Collection getVirtualHostBindings() - { - return Collections.emptySet(); - } - - @Override - public Collection getConnections() - { - return Collections.emptySet(); // TODO - Implement - } - - @Override - public String getName() - { - return getBindingAddress() + ":" + getPort(); // TODO - Implement - } - - @Override - public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException - { - throw new IllegalStateException(); // TODO - Implement - } - - @Override - public State getActualState() - { - return State.ACTIVE; - } - - @Override - public boolean isDurable() - { - return false; // TODO - Implement - } - - @Override - public void setDurable(boolean durable) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - throw new IllegalStateException(); - } - - @Override - public LifetimePolicy getLifetimePolicy() - { - return LifetimePolicy.PERMANENT; - } - - @Override - public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - throw new IllegalStateException(); // TODO - Implement - } - - @Override - public long getTimeToLive() - { - return 0; // TODO - Implement - } - - @Override - public long setTimeToLive(long expected, long desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - throw new IllegalStateException(); // TODO - Implement - } - - @Override - public Statistics getStatistics() - { - return NoStatistics.getInstance(); - } - - @Override - public Collection getChildren(Class clazz) - { - if(clazz == Connection.class) - { - return (Collection) getConnections(); - } - else - { - return Collections.emptySet(); - } - } - - @Override - public C createChild(Class childClass, Map attributes, ConfiguredObject... otherParents) - { - throw new UnsupportedOperationException(); - } - - @Override - public Object getAttribute(String name) - { - if(ID.equals(name)) - { - return getId(); - } - else if(NAME.equals(name)) - { - return getName(); - } - else if(STATE.equals(name)) - { - return getActualState(); - } - else if(DURABLE.equals(name)) - { - return isDurable(); - } - else if(LIFETIME_POLICY.equals(name)) - { - return getLifetimePolicy(); - } - else if(TIME_TO_LIVE.equals(name)) - { - return getTimeToLive(); - } - else if(CREATED.equals(name)) - { - - } - else if(UPDATED.equals(name)) - { - - } - else if(BINDING_ADDRESS.equals(name)) - { - return getBindingAddress(); - } - else if(PORT.equals(name)) - { - return getPort(); - } - else if(PROTOCOLS.equals(name)) - { - return getProtocols(); - } - else if(TRANSPORTS.equals(name)) - { - return getTransports(); - } - - return super.getAttribute(name); //TODO - Implement - } - - @Override - public Collection getAttributeNames() - { - return AVAILABLE_ATTRIBUTES; - } - - @Override - public Object setAttribute(String name, Object expected, Object desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - return super.setAttribute(name, expected, desired); //TODO - Implement - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java new file mode 100644 index 0000000000..113d895e62 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java @@ -0,0 +1,48 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import java.util.Collection; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.KeyStore; + +public class KeyStoreAdapter extends AbstractKeyStoreAdapter implements KeyStore +{ + + public KeyStoreAdapter(UUID id, Broker broker, Map attributes) + { + super(id, broker, attributes); + if (attributes.get(CERTIFICATE_ALIAS) != null) + { + changeAttribute(CERTIFICATE_ALIAS, null, attributes.get(CERTIFICATE_ALIAS)); + } + } + + @Override + public Collection getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java index 7653fcc9b9..c4a531c923 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java @@ -21,7 +21,16 @@ package org.apache.qpid.server.model.adapter; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Connection; import org.apache.qpid.server.model.LifetimePolicy; @@ -30,119 +39,82 @@ import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.VirtualHostAlias; -import org.apache.qpid.server.protocol.AmqpProtocolVersion; -import org.apache.qpid.server.transport.QpidAcceptor; - -import java.net.InetSocketAddress; -import java.security.AccessControlException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import org.apache.qpid.server.configuration.updater.TaskExecutor; public class PortAdapter extends AbstractAdapter implements Port { - private final BrokerAdapter _broker; - private final QpidAcceptor _acceptor; - private final InetSocketAddress _address; - private final Collection _protocols; - - public PortAdapter(BrokerAdapter brokerAdapter, QpidAcceptor acceptor, InetSocketAddress address) - { - super(UUIDGenerator.generateRandomUUID()); - _broker = brokerAdapter; - _acceptor = acceptor; - _address = address; - List protocols = new ArrayList(); + private final Broker _broker; + private AuthenticationProvider _authenticationProvider; - for(AmqpProtocolVersion pv : _acceptor.getSupported()) - { - switch(pv) - { - case v0_8: - protocols.add(Protocol.AMQP_0_8); - break; - case v0_9: - protocols.add(Protocol.AMQP_0_9); - break; - case v0_9_1: - protocols.add(Protocol.AMQP_0_9_1); - break; - case v0_10: - protocols.add(Protocol.AMQP_0_10); - break; - case v1_0_0: - protocols.add(Protocol.AMQP_1_0); - break; - } - } + /* + * TODO register PortAceptor as a listener. For supporting multiple + * protocols on the same port we need to introduce a special entity like + * PortAceptor which will be responsible for port binding/unbinding + */ + public PortAdapter(UUID id, Broker broker, Map attributes, Map defaults, TaskExecutor taskExecutor) + { + super(id, defaults, attributes, taskExecutor); + _broker = broker; - _protocols = Collections.unmodifiableCollection(protocols); + addParent(Broker.class, broker); } @Override public String getBindingAddress() { - return _address.getHostName(); + return (String)getAttribute(BINDING_ADDRESS); } @Override public int getPort() { - return _address.getPort(); + return (Integer)getAttribute(PORT); } + @SuppressWarnings("unchecked") @Override public Collection getTransports() { - switch (_acceptor.getTransport()) - { - case TCP: - return Collections.singleton(Transport.TCP); - case SSL: - return Collections.singleton(Transport.SSL); - } - - return null; // TODO - Implement + return (Collection)getAttribute(TRANSPORTS); } @Override public void addTransport(Transport transport) throws IllegalStateException, AccessControlException, IllegalArgumentException { - throw new IllegalStateException(); // TODO - Implement + throw new IllegalStateException(); } @Override public Transport removeTransport(Transport transport) throws IllegalStateException, AccessControlException, IllegalArgumentException { - throw new IllegalStateException(); // TODO - Implement + throw new IllegalStateException(); } + @SuppressWarnings("unchecked") @Override public Collection getProtocols() { - return _protocols; + return (Collection)getAttribute(PROTOCOLS); } @Override public void addProtocol(Protocol protocol) throws IllegalStateException, AccessControlException, IllegalArgumentException { - throw new IllegalStateException(); // TODO - Implement + throw new IllegalStateException(); } @Override public Protocol removeProtocol(Protocol protocol) throws IllegalStateException, AccessControlException, IllegalArgumentException { - throw new IllegalStateException(); // TODO - Implement + throw new IllegalStateException(); } @Override @@ -165,31 +137,36 @@ public class PortAdapter extends AbstractAdapter implements Port @Override public Collection getConnections() { - return null; // TODO - Implement + return null; } @Override public String getName() { - return getBindingAddress() + ":" + getPort(); // TODO - Implement + return (String)getAttribute(NAME); } @Override public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException { - throw new IllegalStateException(); // TODO - Implement + throw new IllegalStateException(); } @Override public State getActualState() { - return State.ACTIVE; + State state = (State)super.getAttribute(STATE); + if (state == null) + { + return State.ACTIVE; + } + return state; } @Override public boolean isDurable() { - return false; // TODO - Implement + return false; } @Override @@ -209,20 +186,20 @@ public class PortAdapter extends AbstractAdapter implements Port public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) throws IllegalStateException, AccessControlException, IllegalArgumentException { - throw new IllegalStateException(); // TODO - Implement + throw new IllegalStateException(); } @Override public long getTimeToLive() { - return 0; // TODO - Implement + return 0; } @Override public long setTimeToLive(long expected, long desired) throws IllegalStateException, AccessControlException, IllegalArgumentException { - throw new IllegalStateException(); // TODO - Implement + throw new IllegalStateException(); } @Override @@ -257,10 +234,6 @@ public class PortAdapter extends AbstractAdapter implements Port { return getId(); } - else if(NAME.equals(name)) - { - return getName(); - } else if(STATE.equals(name)) { return getActualState(); @@ -285,36 +258,54 @@ public class PortAdapter extends AbstractAdapter implements Port { } - else if(BINDING_ADDRESS.equals(name)) - { - return getBindingAddress(); - } - else if(PORT.equals(name)) + return super.getAttribute(name); + } + + @Override + public Collection getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + + @Override + public boolean setState(State currentState, State desiredState) + { + if (desiredState == State.DELETED) { - return getPort(); + return true; } - else if(PROTOCOLS.equals(name)) + else if (desiredState == State.ACTIVE) { - return getProtocols(); + onActivate(); + return true; } - else if(TRANSPORTS.equals(name)) + else if (desiredState == State.STOPPED) { - return getTransports(); + onStop(); + return true; } + return false; + } - return super.getAttribute(name); //TODO - Implement + protected void onActivate() + { + // no-op: expected to be overridden by subclass } - @Override - public Collection getAttributeNames() + protected void onStop() { - return AVAILABLE_ATTRIBUTES; + // no-op: expected to be overridden by subclass } @Override - public Object setAttribute(String name, Object expected, Object desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException + public AuthenticationProvider getAuthenticationProvider() + { + return _authenticationProvider; + } + + public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) { - return super.setAttribute(name, expected, desired); //TODO - Implement + _authenticationProvider = authenticationProvider; } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java new file mode 100644 index 0000000000..b7441b9f3b --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java @@ -0,0 +1,222 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Protocol.ProtocolType; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.util.MapValueConverter; + +public class PortFactory +{ + public static final int DEFAULT_AMQP_SEND_BUFFER_SIZE = 262144; + public static final int DEFAULT_AMQP_RECEIVE_BUFFER_SIZE = 262144; + public static final boolean DEFAULT_AMQP_NEED_CLIENT_AUTH = false; + public static final boolean DEFAULT_AMQP_WANT_CLIENT_AUTH = false; + public static final boolean DEFAULT_AMQP_TCP_NO_DELAY = true; + public static final String DEFAULT_AMQP_BINDING = "*"; + public static final Transport DEFAULT_TRANSPORT = Transport.TCP; + + private final Collection _defaultProtocols; + + public PortFactory() + { + Set defaultProtocols = EnumSet.of(Protocol.AMQP_0_8, Protocol.AMQP_0_9, Protocol.AMQP_0_9_1, + Protocol.AMQP_0_10, Protocol.AMQP_1_0); + String excludedProtocols = System.getProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES); + if (excludedProtocols != null) + { + String[] excludes = excludedProtocols.split(","); + for (String exclude : excludes) + { + Protocol protocol = Protocol.valueOf(exclude); + defaultProtocols.remove(protocol); + } + } + String includedProtocols = System.getProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES); + if (includedProtocols != null) + { + String[] includes = includedProtocols.split(","); + for (String include : includes) + { + Protocol protocol = Protocol.valueOf(include); + defaultProtocols.add(protocol); + } + } + _defaultProtocols = Collections.unmodifiableCollection(defaultProtocols); + } + + public Port createPort(UUID id, Broker broker, Map objectAttributes) + { + Map attributes = retrieveAttributes(objectAttributes); + + final Port port; + Map defaults = new HashMap(); + defaults.put(Port.TRANSPORTS, Collections.singleton(DEFAULT_TRANSPORT)); + Object portValue = attributes.get(Port.PORT); + if (portValue == null) + { + throw new IllegalConfigurationException("Port attribute is not specified for port: " + attributes); + } + if (isAmqpProtocol(attributes)) + { + Object binding = attributes.get(Port.BINDING_ADDRESS); + if (binding == null) + { + binding = DEFAULT_AMQP_BINDING; + defaults.put(Port.BINDING_ADDRESS, DEFAULT_AMQP_BINDING); + } + defaults.put(Port.NAME, binding + ":" + portValue); + defaults.put(Port.PROTOCOLS, _defaultProtocols); + defaults.put(Port.TCP_NO_DELAY, DEFAULT_AMQP_TCP_NO_DELAY); + defaults.put(Port.WANT_CLIENT_AUTH, DEFAULT_AMQP_WANT_CLIENT_AUTH); + defaults.put(Port.NEED_CLIENT_AUTH, DEFAULT_AMQP_NEED_CLIENT_AUTH); + defaults.put(Port.RECEIVE_BUFFER_SIZE, DEFAULT_AMQP_RECEIVE_BUFFER_SIZE); + defaults.put(Port.SEND_BUFFER_SIZE, DEFAULT_AMQP_SEND_BUFFER_SIZE); + port = new AmqpPortAdapter(id, broker, attributes, defaults, broker.getTaskExecutor()); + } + else + { + @SuppressWarnings("unchecked") + Collection protocols = (Collection)attributes.get(Port.PROTOCOLS); + if (protocols.size() > 1) + { + throw new IllegalConfigurationException("Only one protocol can be used on non AMQP port"); + } + Protocol protocol = protocols.iterator().next(); + defaults.put(Port.NAME, portValue + "-" + protocol.name()); + port = new PortAdapter(id, broker, attributes, defaults, broker.getTaskExecutor()); + } + return port; + } + + private Map retrieveAttributes(Map objectAttributes) + { + Map attributes = new HashMap(objectAttributes); + + if (objectAttributes.containsKey(Port.PROTOCOLS)) + { + final Set protocolSet = MapValueConverter.getEnumSetAttribute(Port.PROTOCOLS, objectAttributes, Protocol.class); + attributes.put(Port.PROTOCOLS, protocolSet); + } + + if (objectAttributes.containsKey(Port.TRANSPORTS)) + { + final Set transportSet = MapValueConverter.getEnumSetAttribute(Port.TRANSPORTS, objectAttributes, + Transport.class); + attributes.put(Port.TRANSPORTS, transportSet); + } + + if (objectAttributes.containsKey(Port.PORT)) + { + Integer port = MapValueConverter.getIntegerAttribute(Port.PORT, objectAttributes); + attributes.put(Port.PORT, port); + } + + if (objectAttributes.containsKey(Port.TCP_NO_DELAY)) + { + boolean tcpNoDelay = MapValueConverter.getBooleanAttribute(Port.TCP_NO_DELAY, objectAttributes); + attributes.put(Port.TCP_NO_DELAY, tcpNoDelay); + } + + if (objectAttributes.containsKey(Port.RECEIVE_BUFFER_SIZE)) + { + int receiveBufferSize = MapValueConverter.getIntegerAttribute(Port.RECEIVE_BUFFER_SIZE, objectAttributes); + attributes.put(Port.RECEIVE_BUFFER_SIZE, receiveBufferSize); + } + + if (objectAttributes.containsKey(Port.SEND_BUFFER_SIZE)) + { + int sendBufferSize = MapValueConverter.getIntegerAttribute(Port.SEND_BUFFER_SIZE, objectAttributes); + attributes.put(Port.SEND_BUFFER_SIZE, sendBufferSize); + } + + if (objectAttributes.containsKey(Port.NEED_CLIENT_AUTH)) + { + boolean needClientAuth = MapValueConverter.getBooleanAttribute(Port.NEED_CLIENT_AUTH, objectAttributes); + attributes.put(Port.NEED_CLIENT_AUTH, needClientAuth); + } + + if (objectAttributes.containsKey(Port.WANT_CLIENT_AUTH)) + { + boolean wantClientAuth = MapValueConverter.getBooleanAttribute(Port.WANT_CLIENT_AUTH, objectAttributes); + attributes.put(Port.WANT_CLIENT_AUTH, wantClientAuth); + } + + if (objectAttributes.containsKey(Port.BINDING_ADDRESS)) + { + String binding = MapValueConverter.getStringAttribute(Port.BINDING_ADDRESS, objectAttributes); + attributes.put(Port.BINDING_ADDRESS, binding); + } + + if (objectAttributes.containsKey(Port.STATE)) + { + State state = MapValueConverter.getEnumAttribute(State.class, Port.STATE, objectAttributes); + attributes.put(Port.STATE, state); + } + return attributes; + } + + private boolean isAmqpProtocol(Map portAttributes) + { + @SuppressWarnings("unchecked") + Set protocols = (Set) portAttributes.get(Port.PROTOCOLS); + if (protocols == null || protocols.isEmpty()) + { + // defaulting to AMQP if protocol is not specified + return true; + } + + Set protocolTypes = new HashSet(); + for (Protocol protocolObject : protocols) + { + protocolTypes.add(protocolObject.getProtocolType()); + } + + if (protocolTypes.size() > 1) + { + throw new IllegalConfigurationException("Found different protocol types '" + protocolTypes + + "' on port configuration: " + portAttributes); + } + + return protocolTypes.contains(ProtocolType.AMQP); + } + + public Collection getDefaultProtocols() + { + return _defaultProtocols; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java index 78f6d38d93..f3ddf32e5a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java @@ -43,6 +43,7 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.queue.*; import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.util.MapValueConverter; final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.SubscriptionRegistrationListener, AMQQueue.NotificationListener { @@ -50,15 +51,16 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs static final Map ATTRIBUTE_MAPPINGS = new HashMap(); static { - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_REPEAT_GAP, "x-qpid-minimum-alert-repeat-gap"); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, "x-qpid-maximum-message-age"); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, "x-qpid-maximum-message-size"); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, "x-qpid-maximum-message-count"); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_REPEAT_GAP, AMQQueueFactory.X_QPID_MINIMUM_ALERT_REPEAT_GAP); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_AGE); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_SIZE); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_COUNT); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, AMQQueueFactory.X_QPID_MAXIMUM_QUEUE_DEPTH); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, "x-qpid-maximum-delivery-count"); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, "x-qpid-capacity"); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, "x-qpid-flow-resume-capacity"); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, AMQQueueFactory.X_QPID_CAPACITY); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, AMQQueueFactory.X_QPID_FLOW_RESUME_CAPACITY); QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.SORT_KEY, AMQQueueFactory.QPID_QUEUE_SORT_KEY); QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.LVQ_KEY, AMQQueueFactory.QPID_LAST_VALUE_QUEUE_KEY); @@ -78,7 +80,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs public QueueAdapter(final VirtualHostAdapter virtualHostAdapter, final AMQQueue queue) { - super(queue.getId()); + super(queue.getId(), virtualHostAdapter.getTaskExecutor()); _vhost = virtualHostAdapter; addParent(org.apache.qpid.server.model.VirtualHost.class, virtualHostAdapter); @@ -205,47 +207,47 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs } @Override - public Object setAttribute(String name, Object expected, Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException + public boolean changeAttribute(String name, Object expected, Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException { try { if(ALERT_REPEAT_GAP.equals(name)) { _queue.setMinimumAlertRepeatGap((Long)desired); - return desired; + return true; } else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name)) { _queue.setMaximumMessageAge((Long)desired); - return desired; + return true; } else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name)) { _queue.setMaximumMessageSize((Long)desired); - return desired; + return true; } else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name)) { _queue.setMaximumQueueDepth((Long)desired); - return desired; + return true; } else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name)) { _queue.setMaximumMessageCount((Long)desired); - return desired; + return true; } else if(ALTERNATE_EXCHANGE.equals(name)) { // In future we may want to accept a UUID as an alternative way to identifying the exchange ExchangeAdapter alternateExchange = (ExchangeAdapter) desired; _queue.setAlternateExchange(alternateExchange == null ? null : alternateExchange.getExchange()); - return desired; + return true; } else if(EXCLUSIVE.equals(name)) { Boolean exclusiveFlag = (Boolean) desired; _queue.setExclusive(exclusiveFlag); - return desired; + return true; } else if(MESSAGE_GROUP_KEY.equals(name)) { @@ -266,7 +268,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name)) { _queue.setMaximumDeliveryCount((Integer)desired); - return desired; + return true; } else if(NO_LOCAL.equals(name)) { @@ -279,12 +281,12 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name)) { _queue.setCapacity((Long)desired); - return desired; + return true; } else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name)) { _queue.setFlowResumeCapacity((Long)desired); - return desired; + return true; } else if(QUEUE_FLOW_STOPPED.equals(name)) { @@ -301,10 +303,10 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs else if (DESCRIPTION.equals(name)) { _queue.setDescription((String) desired); - return desired; + return true; } - return super.setAttribute(name, expected, desired); + return super.changeAttribute(name, expected, desired); } finally { @@ -495,8 +497,8 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs throws AccessControlException, IllegalStateException { attributes = new HashMap(attributes); - String bindingKey = getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, ""); - Map bindingArgs = getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.EMPTY_MAP); + String bindingKey = MapValueConverter.getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, ""); + Map bindingArgs = MapValueConverter.getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.emptyMap()); attributes.remove(org.apache.qpid.server.model.Binding.NAME); attributes.remove(org.apache.qpid.server.model.Binding.ARGUMENTS); @@ -508,7 +510,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs @Override - public C createChild(Class childClass, Map attributes, ConfiguredObject... otherParents) + public C addChild(Class childClass, Map attributes, ConfiguredObject... otherParents) { if(childClass == org.apache.qpid.server.model.Binding.class) { @@ -712,15 +714,15 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs } @Override - public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, + protected boolean setState(State currentState, State desiredState) throws IllegalStateTransitionException, AccessControlException { if (desiredState == State.DELETED) { delete(); - return State.DELETED; + return true; } - return super.setDesiredState(currentState, desiredState); + return false; } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java index d802697d67..2fffdb32f8 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java @@ -34,6 +34,7 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.model.Consumer; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.protocol.AMQSessionModel; final class SessionAdapter extends AbstractAdapter implements Session @@ -44,9 +45,9 @@ final class SessionAdapter extends AbstractAdapter implements Session private AMQSessionModel _session; private SessionStatistics _statistics; - public SessionAdapter(final AMQSessionModel session) + public SessionAdapter(final AMQSessionModel session, TaskExecutor taskExecutor) { - super(UUIDGenerator.generateRandomUUID()); + super(UUIDGenerator.generateRandomUUID(), taskExecutor); _session = session; _statistics = new SessionStatistics(); } @@ -141,13 +142,6 @@ final class SessionAdapter extends AbstractAdapter implements Session return super.getAttribute(name); //TODO - Implement } - @Override - public Object setAttribute(String name, Object expected, Object desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - return super.setAttribute(name, expected, desired); //TODO - Implement - } - public Statistics getStatistics() { return _statistics; @@ -237,4 +231,11 @@ final class SessionAdapter extends AbstractAdapter implements Session return null; // TODO - Implement } } + + @Override + protected boolean setState(State currentState, State desiredState) + { + // TODO : add state management + return false; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java new file mode 100644 index 0000000000..bdffe605ec --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java @@ -0,0 +1,43 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import java.util.Collection; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.TrustStore; + +public class TrustStoreAdapter extends AbstractKeyStoreAdapter implements TrustStore +{ + public TrustStoreAdapter(UUID id, Broker broker, Map attributes) + { + super(id, broker, attributes); + } + + @Override + public Collection getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java index 35838e51d2..1d50be279f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.model.adapter; +import java.io.File; import java.security.AccessControlException; import java.security.Principal; import java.util.ArrayList; @@ -31,17 +32,27 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; + +import org.apache.commons.configuration.CompositeConfiguration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration.SystemConfiguration; import org.apache.qpid.AMQException; import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.configuration.XmlConfigurationUtilities.MyConfiguration; import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.exchange.ExchangeType; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Connection; import org.apache.qpid.server.model.Exchange; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.QueueType; import org.apache.qpid.server.model.State; @@ -49,22 +60,38 @@ import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.util.MapValueConverter; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, ExchangeRegistry.RegistryChangeListener, +public final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, ExchangeRegistry.RegistryChangeListener, QueueRegistry.RegistryChangeListener, IConnectionRegistry.RegistryChangeListener { - private final org.apache.qpid.server.virtualhost.VirtualHost _virtualHost; + @SuppressWarnings("serial") + public static final Map> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap>(){{ + put(NAME, String.class); + put(STORE_PATH, String.class); + put(STORE_TYPE, String.class); + put(CONFIG_PATH, String.class); + put(STATE, State.class); + }}); + + private org.apache.qpid.server.virtualhost.VirtualHost _virtualHost; private final Map _connectionAdapters = new HashMap(); @@ -74,37 +101,52 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E private final Map _exchangeAdapters = new HashMap(); - - private final StatisticsAdapter _statistics; - - private final BrokerAdapter _broker; - + private StatisticsAdapter _statistics; + private final Broker _broker; private final List _aliases = new ArrayList(); + private StatisticsGatherer _brokerStatisticsGatherer; - - VirtualHostAdapter(BrokerAdapter brokerAdapter, - final org.apache.qpid.server.virtualhost.VirtualHost virtualHost) + public VirtualHostAdapter(UUID id, Map attributes, Broker broker, StatisticsGatherer brokerStatisticsGatherer, TaskExecutor taskExecutor) { - super(virtualHost.getId()); - _broker = brokerAdapter; - _virtualHost = virtualHost; - _statistics = new VirtualHostStatisticsAdapter(virtualHost); - virtualHost.getQueueRegistry().addRegistryChangeListener(this); - populateQueues(); - virtualHost.getExchangeRegistry().addRegistryChangeListener(this); - populateExchanges(); - virtualHost.getConnectionRegistry().addRegistryChangeListener(this); - populateConnections(); - + super(id, null, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); + validateAttributes(); + _broker = broker; + _brokerStatisticsGatherer = brokerStatisticsGatherer; + addParent(Broker.class, broker); + } + private void validateAttributes() + { + String name = getName(); + if (name == null || "".equals(name.trim())) + { + throw new IllegalConfigurationException("Virtual host name must be specified"); + } - for(Port port :_broker.getPorts()) + String configurationFile = (String) getAttribute(CONFIG_PATH); + String storePath = (String) getAttribute(STORE_PATH); + String storeType = (String) getAttribute(STORE_TYPE); + boolean invalidAttributes = false; + if (configurationFile == null) + { + if (storePath == null || storeType == null) + { + invalidAttributes = true; + } + } + else + { + if (storePath != null || storeType != null) + { + invalidAttributes = true; + } + } + if (invalidAttributes) { - _aliases.add(new VirtualHostAliasAdapter(this, port)); + throw new IllegalConfigurationException("Please specify either the 'configPath' attribute or both 'storePath' and 'storeType' attributes"); } } - private void populateExchanges() { Collection actualExchanges = @@ -126,37 +168,22 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E private void populateQueues() { Collection actualQueues = _virtualHost.getQueueRegistry().getQueues(); - - synchronized(_queueAdapters) - { - for(AMQQueue queue : actualQueues) - { - if(!_queueAdapters.containsKey(queue)) - { - _queueAdapters.put(queue, new QueueAdapter(this,queue)); - } - } - } - } - - private void populateConnections() - { - - List actualConnections = _virtualHost.getConnectionRegistry().getConnections(); - - synchronized(_connectionAdapters) + if ( actualQueues != null ) { - for(AMQConnectionModel conn : actualConnections) + synchronized(_queueAdapters) { - if(!_connectionAdapters.containsKey(conn)) + for(AMQQueue queue : actualQueues) { - _connectionAdapters.put(conn, new ConnectionAdapter(conn)); + if(!_queueAdapters.containsKey(queue)) + { + _queueAdapters.put(queue, new QueueAdapter(this, queue)); + } } } } - } + @Override public String getReplicationGroupName() { return null; //TODO @@ -198,12 +225,12 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E { attributes = new HashMap(attributes); - String name = getStringAttribute(Exchange.NAME, attributes, null); - State state = getEnumAttribute(State.class, Exchange.STATE, attributes, State.ACTIVE); - boolean durable = getBooleanAttribute(Exchange.DURABLE, attributes, false); - LifetimePolicy lifetime = getEnumAttribute(LifetimePolicy.class, Exchange.LIFETIME_POLICY, attributes, LifetimePolicy.PERMANENT); - String type = getStringAttribute(Exchange.TYPE, attributes, null); - long ttl = getLongAttribute(Exchange.TIME_TO_LIVE, attributes, 0l); + String name = MapValueConverter.getStringAttribute(Exchange.NAME, attributes, null); + State state = MapValueConverter.getEnumAttribute(State.class, Exchange.STATE, attributes, State.ACTIVE); + boolean durable = MapValueConverter.getBooleanAttribute(Exchange.DURABLE, attributes, false); + LifetimePolicy lifetime = MapValueConverter.getEnumAttribute(LifetimePolicy.class, Exchange.LIFETIME_POLICY, attributes, LifetimePolicy.PERMANENT); + String type = MapValueConverter.getStringAttribute(Exchange.TYPE, attributes, null); + long ttl = MapValueConverter.getLongAttribute(Exchange.TIME_TO_LIVE, attributes, 0l); attributes.remove(Exchange.NAME); attributes.remove(Exchange.STATE); @@ -266,7 +293,7 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E if (attributes.containsKey(Queue.TYPE)) { - String typeAttribute = getStringAttribute(Queue.TYPE, attributes, null); + String typeAttribute = MapValueConverter.getStringAttribute(Queue.TYPE, attributes, null); QueueType queueType = null; try { @@ -289,12 +316,12 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E throw new IllegalArgumentException("Sort key is not specified for sorted queue"); } } - String name = getStringAttribute(Queue.NAME, attributes, null); - State state = getEnumAttribute(State.class, Queue.STATE, attributes, State.ACTIVE); - boolean durable = getBooleanAttribute(Queue.DURABLE, attributes, false); - LifetimePolicy lifetime = getEnumAttribute(LifetimePolicy.class, Queue.LIFETIME_POLICY, attributes, LifetimePolicy.PERMANENT); - long ttl = getLongAttribute(Queue.TIME_TO_LIVE, attributes, 0l); - boolean exclusive= getBooleanAttribute(Queue.EXCLUSIVE, attributes, false); + String name = MapValueConverter.getStringAttribute(Queue.NAME, attributes, null); + State state = MapValueConverter.getEnumAttribute(State.class, Queue.STATE, attributes, State.ACTIVE); + boolean durable = MapValueConverter.getBooleanAttribute(Queue.DURABLE, attributes, false); + LifetimePolicy lifetime = MapValueConverter.getEnumAttribute(LifetimePolicy.class, Queue.LIFETIME_POLICY, attributes, LifetimePolicy.PERMANENT); + long ttl = MapValueConverter.getLongAttribute(Queue.TIME_TO_LIVE, attributes, 0l); + boolean exclusive= MapValueConverter.getBooleanAttribute(Queue.EXCLUSIVE, attributes, false); attributes.remove(Queue.NAME); attributes.remove(Queue.STATE); @@ -328,11 +355,10 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E String owner = null; if(exclusive) { - Set principals = - SecurityManager.getThreadSubject().getPrincipals(); - if(principals != null && !principals.isEmpty()) + Principal authenticatedPrincipal = AuthenticatedPrincipal.getOptionalAuthenticatedPrincipalFromSubject(SecurityManager.getThreadSubject()); + if(authenticatedPrincipal != null) { - owner = principals.iterator().next().getName(); + owner = authenticatedPrincipal.getName(); } } try @@ -370,7 +396,7 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E public String getName() { - return _virtualHost.getName(); + return (String)getAttribute(NAME); } public String setName(final String currentName, final String desiredName) @@ -379,9 +405,36 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E throw new IllegalStateException(); } + @Override public State getActualState() { - return getDesiredState(); + if (_virtualHost == null) + { + State state = (State)super.getAttribute(STATE); + if (state == null) + { + return State.INITIALISING; + } + return state; + } + else + { + org.apache.qpid.server.virtualhost.State implementationState = _virtualHost.getState(); + switch(implementationState) + { + case INITIALISING: + return State.INITIALISING; + case ACTIVE: + return State.ACTIVE; + case PASSIVE: + return State.QUIESCED; + case STOPPED: + return State.STOPPED; + default: + // unexpected state + return null; + } + } } public boolean isDurable() @@ -448,7 +501,7 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E } @Override - public C createChild(Class childClass, Map attributes, ConfiguredObject... otherParents) + public C addChild(Class childClass, Map attributes, ConfiguredObject... otherParents) { if(childClass == Exchange.class) { @@ -548,7 +601,7 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E { if(!_connectionAdapters.containsKey(connection)) { - adapter = new ConnectionAdapter(connection); + adapter = new ConnectionAdapter(connection, getTaskExecutor()); _connectionAdapters.put(connection, adapter); } @@ -709,13 +762,9 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E { return getId(); } - else if(NAME.equals(name)) - { - return getName(); - } else if(STATE.equals(name)) { - return State.ACTIVE; + return getActualState(); } else if(DURABLE.equals(name)) { @@ -737,10 +786,19 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E { // TODO } - else if(SUPPORTED_EXCHANGE_TYPES.equals(name)) + else if (_virtualHost != null) + { + return getAttributeFromVirtualHostImplementation(name); + } + return super.getAttribute(name); + } + + private Object getAttributeFromVirtualHostImplementation(String name) + { + if(SUPPORTED_EXCHANGE_TYPES.equals(name)) { List types = new ArrayList(); - for(ExchangeType type : _virtualHost.getExchangeFactory().getRegisteredTypes()) + for(@SuppressWarnings("rawtypes") ExchangeType type : _virtualHost.getExchangeFactory().getRegisteredTypes()) { types.add(type.getName().asString()); } @@ -754,10 +812,6 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E { return _virtualHost.getConfiguration().isDeadLetterQueueEnabled(); } - else if(FEDERATION_TAG.equals(name)) - { - return _virtualHost.getFederationTag(); - } else if(HOUSEKEEPING_CHECK_PERIOD.equals(name)) { return _virtualHost.getConfiguration().getHousekeepingCheckPeriod(); @@ -778,9 +832,9 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E { return _virtualHost.getMessageStore().getStoreType(); } - else if(STORE_CONFIGURATION.equals(name)) + else if(STORE_PATH.equals(name)) { - // TODO + return _virtualHost.getMessageStore().getStoreLocation(); } else if(STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE.equals(name)) { @@ -821,13 +875,6 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E return super.getAttribute(name); } - @Override - public Object setAttribute(String name, Object expected, Object desired) - throws IllegalStateException, AccessControlException, IllegalArgumentException - { - return super.setAttribute(name, expected, desired); //TODO - Implement - } - @Override public Collection getAttributeNames() { @@ -889,4 +936,111 @@ final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, E } } + + @Override + protected boolean setState(State currentState, State desiredState) + { + if (desiredState == State.ACTIVE) + { + activate(); + return true; + } + else if (desiredState == State.STOPPED) + { + if (_virtualHost != null) + { + try + { + _virtualHost.close(); + } + finally + { + _broker.getVirtualHostRegistry().unregisterVirtualHost(_virtualHost); + } + } + return true; + } + else if (desiredState == State.DELETED) + { + //TODO: add ACL check to authorize the operation + if (_virtualHost != null && _virtualHost.getState() == org.apache.qpid.server.virtualhost.State.ACTIVE) + { + setDesiredState(currentState, State.STOPPED); + } + return true; + } + return false; + } + + private void activate() + { + VirtualHostRegistry virtualHostRegistry = _broker.getVirtualHostRegistry(); + String virtualHostName = getName(); + try + { + VirtualHostConfiguration configuration = createVirtualHostConfiguration(virtualHostName); + _virtualHost = new VirtualHostImpl(_broker.getVirtualHostRegistry(), _brokerStatisticsGatherer, _broker.getSecurityManager(), configuration); + } + catch (Exception e) + { + throw new RuntimeException("Failed to create virtual host " + virtualHostName, e); + } + + virtualHostRegistry.registerVirtualHost(_virtualHost); + + _statistics = new VirtualHostStatisticsAdapter(_virtualHost); + _virtualHost.getQueueRegistry().addRegistryChangeListener(this); + populateQueues(); + _virtualHost.getExchangeRegistry().addRegistryChangeListener(this); + populateExchanges(); + _virtualHost.getConnectionRegistry().addRegistryChangeListener(this); + + synchronized(_aliases) + { + for(Port port :_broker.getPorts()) + { + if (Protocol.hasAmqpProtocol(port.getProtocols())) + { + _aliases.add(new VirtualHostAliasAdapter(this, port)); + } + } + } + } + + private VirtualHostConfiguration createVirtualHostConfiguration(String virtualHostName) throws ConfigurationException + { + VirtualHostConfiguration configuration; + String configurationFile = (String)getAttribute(CONFIG_PATH); + if (configurationFile == null) + { + final MyConfiguration basicConfiguration = new MyConfiguration(); + PropertiesConfiguration config = new PropertiesConfiguration(); + config.addProperty("store.type", (String)getAttribute(STORE_TYPE)); + config.addProperty("store.environment-path", (String)getAttribute(STORE_PATH)); + basicConfiguration.addConfiguration(config); + + CompositeConfiguration compositeConfiguration = new CompositeConfiguration(); + compositeConfiguration.addConfiguration(new SystemConfiguration()); + compositeConfiguration.addConfiguration(basicConfiguration); + configuration = new VirtualHostConfiguration(virtualHostName, compositeConfiguration , _broker); + } + else + { + configuration = new VirtualHostConfiguration(virtualHostName, new File(configurationFile) , _broker); + } + return configuration; + } + + @Override + public SecurityManager getSecurityManager() + { + return _virtualHost.getSecurityManager(); + } + + @Override + public MessageStore getMessageStore() + { + return _virtualHost.getMessageStore(); + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java index 367d1ff518..91b705b004 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java @@ -43,7 +43,7 @@ public class VirtualHostAliasAdapter extends AbstractAdapter implements Virtual public VirtualHostAliasAdapter(VirtualHostAdapter virtualHostAdapter, Port port) { - super(UUIDGenerator.generateVhostAliasUUID(virtualHostAdapter.getName(), port.getName())); + super(UUIDGenerator.generateVhostAliasUUID(virtualHostAdapter.getName(), port.getName()), virtualHostAdapter.getTaskExecutor()); _vhost = virtualHostAdapter; _port = port; } @@ -140,4 +140,11 @@ public class VirtualHostAliasAdapter extends AbstractAdapter implements Virtual { throw new UnsupportedOperationException(); } + + @Override + protected boolean setState(State currentState, State desiredState) + { + // TODO: state is not supported at the moment + return false; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java index a68ac5439c..917215a42f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java @@ -218,55 +218,71 @@ class ProtocolOutputConverterImpl implements ProtocolOutputConverter final boolean isRedelivered = entry.isRedelivered(); - final AMQBody returnBlock = new AMQBody() - { - - private AMQBody _underlyingBody; - - public AMQBody createAMQBody() - { - return _methodRegistry.createBasicDeliverBody(consumerTag, - deliveryTag, - isRedelivered, - exchangeName, - routingKey); - - + final AMQBody returnBlock = new EncodedDeliveryBody(deliveryTag, routingKey, exchangeName, consumerTag, isRedelivered); + return returnBlock; + } + private class EncodedDeliveryBody implements AMQBody + { + private final long _deliveryTag; + private final AMQShortString _routingKey; + private final AMQShortString _exchangeName; + private final AMQShortString _consumerTag; + private final boolean _isRedelivered; + private AMQBody _underlyingBody; + + private EncodedDeliveryBody(long deliveryTag, AMQShortString routingKey, AMQShortString exchangeName, AMQShortString consumerTag, boolean isRedelivered) + { + _deliveryTag = deliveryTag; + _routingKey = routingKey; + _exchangeName = exchangeName; + _consumerTag = consumerTag; + _isRedelivered = isRedelivered; + } + public AMQBody createAMQBody() + { + return _methodRegistry.createBasicDeliverBody(_consumerTag, + _deliveryTag, + _isRedelivered, + _exchangeName, + _routingKey); + } - } + public byte getFrameType() + { + return AMQMethodBody.TYPE; + } - public byte getFrameType() + public int getSize() + { + if(_underlyingBody == null) { - return AMQMethodBody.TYPE; + _underlyingBody = createAMQBody(); } + return _underlyingBody.getSize(); + } - public int getSize() + public void writePayload(DataOutput buffer) throws IOException + { + if(_underlyingBody == null) { - if(_underlyingBody == null) - { - _underlyingBody = createAMQBody(); - } - return _underlyingBody.getSize(); + _underlyingBody = createAMQBody(); } + _underlyingBody.writePayload(buffer); + } - public void writePayload(DataOutput buffer) throws IOException - { - if(_underlyingBody == null) - { - _underlyingBody = createAMQBody(); - } - _underlyingBody.writePayload(buffer); - } + public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession) + throws AMQException + { + throw new AMQException("This block should never be dispatched!"); + } - public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession) - throws AMQException - { - throw new AMQException("This block should never be dispatched!"); - } - }; - return returnBlock; + @Override + public String toString() + { + return "[" + getClass().getSimpleName() + " underlyingBody: " + String.valueOf(_underlyingBody) + "]"; + } } private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize) @@ -368,7 +384,6 @@ class ProtocolOutputConverterImpl implements ProtocolOutputConverter _methodBody = methodBody; _headerBody = headerBody; _contentBody = contentBody; - } public long getSize() @@ -380,6 +395,19 @@ class ProtocolOutputConverterImpl implements ProtocolOutputConverter { AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody); } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("[").append(getClass().getSimpleName()) + .append(" methodBody=").append(_methodBody) + .append(", headerBody=").append(_headerBody) + .append(", contentBody=").append(_contentBody) + .append(", channel=").append(_channel).append("]"); + return builder.toString(); + } + } public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock @@ -408,6 +436,17 @@ class ProtocolOutputConverterImpl implements ProtocolOutputConverter { AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody); } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append(getClass().getSimpleName()) + .append("methodBody=").append(_methodBody) + .append(", headerBody=").append(_headerBody) + .append(", channel=").append(_channel).append("]"); + return builder.toString(); + } } } \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java b/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java new file mode 100644 index 0000000000..7708b90efc --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/plugin/AccessControlFactory.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.plugin; + +import java.util.Map; + +import org.apache.qpid.server.security.AccessControl; + +public interface AccessControlFactory +{ + AccessControl createInstance(Map attributes); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugin/AuthenticationManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/plugin/AuthenticationManagerFactory.java new file mode 100644 index 0000000000..95e6b4feb0 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/plugin/AuthenticationManagerFactory.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.plugin; + +import java.util.Map; + +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; + + +public interface AuthenticationManagerFactory +{ + public static final String ATTRIBUTE_TYPE = "authenticationProviderType"; + + AuthenticationManager createInstance(Map attributes); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java b/java/broker/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java new file mode 100644 index 0000000000..40ef6ad6a2 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java @@ -0,0 +1,36 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.plugin; + +import java.util.UUID; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public interface ExchangeType +{ + public AMQShortString getName(); + public T newInstance(UUID id, VirtualHost host, AMQShortString name, + boolean durable, int ticket, boolean autoDelete) throws AMQException; + public AMQShortString getDefaultExchangeName(); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java new file mode 100644 index 0000000000..5d80ca24fd --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/plugin/GroupManagerFactory.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.plugin; + +import java.util.Map; + +import org.apache.qpid.server.security.group.GroupManager; + +public interface GroupManagerFactory +{ + GroupManager createInstance(Map attributes); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugin/PluginFactory.java b/java/broker/src/main/java/org/apache/qpid/server/plugin/PluginFactory.java new file mode 100644 index 0000000000..af24f62e28 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/plugin/PluginFactory.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.plugin; + +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Plugin; + +public interface PluginFactory +{ + static final String PLUGIN_TYPE = "pluginType"; + + Plugin createInstance(UUID id, Map attributes, Broker broker); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugin/QpidServiceLoader.java b/java/broker/src/main/java/org/apache/qpid/server/plugin/QpidServiceLoader.java new file mode 100644 index 0000000000..a0e0346ce0 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/plugin/QpidServiceLoader.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.plugin; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.ServiceLoader; + +import org.apache.log4j.Logger; + +/** + * Simple facade over a {@link ServiceLoader} to instantiate all configured implementations of an interface. + */ +public class QpidServiceLoader +{ + private static final Logger _logger = Logger.getLogger(QpidServiceLoader.class); + + public Iterable instancesOf(Class clazz) + { + return instancesOf(clazz, false); + } + + /** + * @throws RuntimeException if at least one implementation is not found. + */ + public Iterable atLeastOneInstanceOf(Class clazz) + { + return instancesOf(clazz, true); + } + + private Iterable instancesOf(Class clazz, boolean atLeastOne) + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Iterator serviceLoaderIterator = ServiceLoader.load(clazz, classLoader).iterator(); + + // create a new list so we can log the count + List serviceImplementations = new ArrayList(); + while(serviceLoaderIterator.hasNext()) + { + serviceImplementations.add(serviceLoaderIterator.next()); + } + + if(atLeastOne && serviceImplementations.isEmpty()) + { + throw new RuntimeException("At least one implementation of " + clazz + " expected"); + } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Found " + serviceImplementations.size() + " implementations of " + clazz); + } + + return serviceImplementations; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/Activator.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/Activator.java deleted file mode 100644 index 12e1eee9ca..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/plugins/Activator.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.server.plugins; - -import org.apache.log4j.Logger; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.registry.ApplicationRegistry; - -public class Activator implements BundleActivator -{ - private static final Logger _logger = Logger.getLogger(Activator.class); - - private BundleContext _context = null; - - public void start(BundleContext ctx) throws Exception - { - _context = ctx; - _logger.info("Registering bundle: " + _context.getBundle().getSymbolicName()); - ctx.registerService(ServerConfiguration.class.getName(), ApplicationRegistry.getInstance().getConfiguration(), null); - } - - public void stop(BundleContext ctx) throws Exception - { - _logger.info("Stopping bundle: " + _context.getBundle().getSymbolicName()); - _context = null; - } - - public BundleContext getContext() - { - return _context; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java deleted file mode 100644 index d2bb3e037c..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java +++ /dev/null @@ -1,91 +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.plugins; - -import org.osgi.framework.Version; - -import java.util.Iterator; -import java.util.Map; - -/** - * Utility class to convert a map of package name to version numbers into the string - * with the format expected of a OSGi system package declaration: - * - * - * org.xyz; version=1.0.0, org.xyz.xyz; version=1.0.0,... - * - * - * Additionally, if the caller has provided a qpidPackageReleaseNumber and the package - * begins org.apache.qpid, this release number will be used, in preference to the one - * found in the Map. - * - * @see org.osgi.framework.Constants#FRAMEWORK_SYSTEMPACKAGES - * - */ -public class OsgiSystemPackageUtil -{ - private static final String APACHE_QPID_PKG_PREFIX = "org.apache.qpid"; - - private final Map _packageNameVersionMap; - private final Version _qpidPackageReleaseNumber; - - public OsgiSystemPackageUtil(final Version qpidPackageReleaseNumber, final Map packageNameVersionMap) - { - _qpidPackageReleaseNumber = qpidPackageReleaseNumber; - _packageNameVersionMap = packageNameVersionMap; - } - - public String getFormattedSystemPackageString() - { - if (_packageNameVersionMap == null || _packageNameVersionMap.size() == 0) - { - return null; - } - - final StringBuilder packages = new StringBuilder(); - - for(Iterator itr = _packageNameVersionMap.keySet().iterator(); itr.hasNext();) - { - final String packageName = itr.next(); - final String packageVersion; - - if (_qpidPackageReleaseNumber != null && packageName.startsWith(APACHE_QPID_PKG_PREFIX)) - { - packageVersion = _qpidPackageReleaseNumber.toString(); - } - else - { - packageVersion = _packageNameVersionMap.get(packageName); - } - - packages.append(packageName); - packages.append("; "); - packages.append("version="); - packages.append(packageVersion); - - if (itr.hasNext()) - { - packages.append(", "); - } - } - - return packages.toString(); - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties b/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties deleted file mode 100644 index 6479546355..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties +++ /dev/null @@ -1,135 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one# -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# -# OSGi framework system package list -# -# PluginManager uses these properties to construct the FRAMEWORK_SYSTEMPACKAGES list -# - -# Format is: -# = -# and PluginManager will convert this into: -# ; version= -# e.g. org.osgi.framework; version=1.3.0 - -javax.management.openmbean=1.0.0 -javax.management=1.0.0 -javax.management.remote.rmi=1.0.0 -javax.management.remote=1.0.0 -javax.management.monitor=1.0.0 - -javax.crypto=1 -javax.crypto.spec=1 - -javax.servlet=2 -javax.servlet.http=2 - -javax.security.auth=1.0.0 -javax.security.auth.callback=1.0.0 -javax.security.auth.login=1.0.0 -javax.security.sasl=1.0.0 -javax.security=1.0.0 - -javax.rmi.ssl=1.0.0 - -org.xml.sax=1.0.0 -org.xml.sax.helpers=1.0.0 - -org.osgi.framework=1.3.0 -org.osgi.service.packageadmin=1.2.0 -org.osgi.service.startlevel=1.0.0 -org.osgi.service.url=1.0.0 -org.osgi.util.tracker=1.0.0 - -org.apache.commons.codec=1.3.0 -org.apache.commons.codec.binary=1.3.0 - -org.apache.commons.configuration=1.0.0 - -org.apache.commons.lang=1.0.0 -org.apache.commons.lang.builder=1.0.0 -org.apache.commons.lang.time=1.0.0 -org.apache.commons.logging=1.0.0 - -org.apache.log4j=1.2.16 - -org.slf4j=1.6.1 - -org.eclipse.jetty=7.6.3 -org.eclipse.jetty.http=7.6.3 -org.eclipse.jetty.io=7.6.3 -org.eclipse.jetty.io.nio=7.6.3 -org.eclipse.jetty.security=7.6.3 -org.eclipse.jetty.server=7.6.3 -org.eclipse.jetty.server.session=7.6.3 -org.eclipse.jetty.server.ssl=7.6.3 -org.eclipse.jetty.server.nio=7.6.3 -org.eclipse.jetty.servlet=7.6.3 -org.eclipse.jetty.util.ssl=7.6.3 - -org.codehaus.jackson=1.9.0 -org.codehaus.jackson.map=1.9.0 - -# For Qpid packages (org.apache.qpid), the version number is automatically overridden by QpidPropertis#getReleaseVersion() - -org.apache.qpid=0.0.0 -org.apache.qpid.common=0.0.0 -org.apache.qpid.exchange=0.0.0 -org.apache.qpid.framing=0.0.0 -org.apache.qpid.management.common.mbeans.annotations=0.0.0 -org.apache.qpid.management.common.mbeans=0.0.0 -org.apache.qpid.protocol=0.0.0 -org.apache.qpid.transport=0.0.0 -org.apache.qpid.transport.codec=0.0.0 -org.apache.qpid.server.binding=0.0.0 -org.apache.qpid.server.model=0.0.0 -org.apache.qpid.server.model.adapter=0.0.0 -org.apache.qpid.server.model.impl=0.0.0 -org.apache.qpid.server.configuration=0.0.0 -org.apache.qpid.server.configuration.plugins=0.0.0 -org.apache.qpid.server.configuration.management=0.0.0 -org.apache.qpid.server.connection=0.0.0 -org.apache.qpid.server.exchange=0.0.0 -org.apache.qpid.server.logging=0.0.0 -org.apache.qpid.server.logging.log4j=0.0.0 -org.apache.qpid.server.logging.actors=0.0.0 -org.apache.qpid.server.logging.messages=0.0.0 -org.apache.qpid.server.logging.subjects=0.0.0 -org.apache.qpid.server.message=0.0.0 -org.apache.qpid.server.persistent=0.0.0 -org.apache.qpid.server.plugins=0.0.0 -org.apache.qpid.server.protocol=0.0.0 -org.apache.qpid.server.queue=0.0.0 -org.apache.qpid.server.subscription=0.0.0 -org.apache.qpid.server.registry=0.0.0 -org.apache.qpid.server.security=0.0.0 -org.apache.qpid.server.security.access=0.0.0 -org.apache.qpid.server.security.access.plugins=0.0.0 -org.apache.qpid.server.security.auth=0.0.0 -org.apache.qpid.server.security.auth.sasl=0.0.0 -org.apache.qpid.server.security.auth.manager=0.0.0 -org.apache.qpid.server.security.auth.rmi=0.0.0 -org.apache.qpid.server.stats=0.0.0 -org.apache.qpid.server.virtualhost=0.0.0 -org.apache.qpid.server.virtualhost.plugins=0.0.0 -org.apache.qpid.util=0.0.0 - -org.apache.qpid.server.store.berkeleydb=0.0.0 - diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java deleted file mode 100644 index 6dcf688f2a..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java +++ /dev/null @@ -1,32 +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.plugins; - -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; - -public interface Plugin -{ - - /** - * Provide Configuration to this plugin - */ - public void configure(ConfigurationPlugin config) throws ConfigurationException; -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginFactory.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginFactory.java deleted file mode 100644 index 7ea2b95b89..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginFactory.java +++ /dev/null @@ -1,32 +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.plugins; - -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; - -public interface PluginFactory

-{ - public Class

getPluginClass(); - - public String getPluginName(); - - public P newInstance(ConfigurationPlugin config) throws ConfigurationException; -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java deleted file mode 100644 index 74abbccd2b..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java +++ /dev/null @@ -1,403 +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.plugins; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.felix.framework.Felix; -import org.apache.felix.framework.util.StringMap; -import org.apache.log4j.Logger; -import org.apache.qpid.common.Closeable; -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.server.configuration.TopicConfiguration; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionConfiguration.SlowConsumerDetectionConfigurationFactory; -import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionPolicyConfiguration.SlowConsumerDetectionPolicyConfigurationFactory; -import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionQueueConfiguration.SlowConsumerDetectionQueueConfigurationFactory; -import org.apache.qpid.server.exchange.ExchangeType; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.SecurityPluginFactory; -import org.apache.qpid.server.security.access.plugins.LegacyAccess; -import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory; -import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager; -import org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManager; -import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; -import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager; -import org.apache.qpid.server.virtualhost.plugins.SlowConsumerDetection; -import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory; -import org.apache.qpid.server.virtualhost.plugins.policies.TopicDeletePolicy; -import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPluginFactory; -import org.apache.qpid.util.FileUtils; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.Version; -import org.osgi.framework.launch.Framework; -import org.osgi.util.tracker.ServiceTracker; - -import static org.apache.felix.framework.util.FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP; -import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_ACTION_PROPERY; -import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_DIR_PROPERY; -import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_INSTALL_VALUE; -import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_START_VALUE; -import static org.apache.felix.main.AutoProcessor.process; -import static org.osgi.framework.Constants.FRAMEWORK_STORAGE; -import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN; -import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT; -import static org.osgi.framework.Constants.FRAMEWORK_SYSTEMPACKAGES; - -/** - * Provides access to pluggable elements, such as exchanges - */ -@SuppressWarnings("unchecked") -public class PluginManager implements Closeable -{ - private static final Logger _logger = Logger.getLogger(PluginManager.class); - - private static final int FELIX_STOP_TIMEOUT = 30000; - - private Framework _felix; - - private ServiceTracker _exchangeTracker = null; - private ServiceTracker _securityTracker = null; - private ServiceTracker _configTracker = null; - private ServiceTracker _virtualHostTracker = null; - private ServiceTracker _policyTracker = null; - private ServiceTracker _authenticationManagerTracker = null; - - private Activator _activator; - - private final List _trackers = new ArrayList(); - private Map _securityPlugins = new HashMap(); - private Map, ConfigurationPluginFactory> _configPlugins = new IdentityHashMap, ConfigurationPluginFactory>(); - private Map _vhostPlugins = new HashMap(); - private Map _policyPlugins = new HashMap(); - private Map> _authenticationManagerPlugins = new HashMap>(); - - /** The default name of the OSGI system package list. */ - private static final String DEFAULT_RESOURCE_NAME = "org/apache/qpid/server/plugins/OsgiSystemPackages.properties"; - - /** The name of the override system property that holds the name of the OSGI system package list. */ - private static final String FILE_PROPERTY = "qpid.osgisystempackages.properties"; - - private static final String OSGI_SYSTEM_PACKAGES; - - static - { - final String filename = System.getProperty(FILE_PROPERTY); - final InputStream is = FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME, - PluginManager.class.getClassLoader()); - - try - { - Version qpidReleaseVersion; - try - { - qpidReleaseVersion = Version.parseVersion(QpidProperties.getReleaseVersion()); - } - catch (IllegalArgumentException iae) - { - qpidReleaseVersion = null; - } - - final Properties p = new Properties(); - p.load(is); - - final OsgiSystemPackageUtil osgiSystemPackageUtil = new OsgiSystemPackageUtil(qpidReleaseVersion, (Map)p); - - OSGI_SYSTEM_PACKAGES = osgiSystemPackageUtil.getFormattedSystemPackageString(); - - _logger.debug("List of OSGi system packages to be added: " + OSGI_SYSTEM_PACKAGES); - } - catch (IOException e) - { - _logger.error("Error reading OSGI system package list", e); - throw new ExceptionInInitializerError(e); - } - } - - - public PluginManager(String pluginPath, String cachePath, BundleContext bundleContext) throws Exception - { - // Store all non-OSGi plugins - // A little gross that we have to add them here, but not all the plugins are OSGIfied - for (SecurityPluginFactory pluginFactory : Arrays.asList(LegacyAccess.FACTORY)) - { - _securityPlugins.put(pluginFactory.getPluginName(), pluginFactory); - } - for (ConfigurationPluginFactory configFactory : Arrays.asList( - TopicConfiguration.FACTORY, - SecurityManager.SecurityConfiguration.FACTORY, - LegacyAccess.LegacyAccessConfiguration.FACTORY, - new SlowConsumerDetectionConfigurationFactory(), - new SlowConsumerDetectionPolicyConfigurationFactory(), - new SlowConsumerDetectionQueueConfigurationFactory(), - PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration.FACTORY, - AnonymousAuthenticationManager.AnonymousAuthenticationManagerConfiguration.FACTORY, - KerberosAuthenticationManager.KerberosAuthenticationManagerConfiguration.FACTORY, - SimpleLDAPAuthenticationManager.SimpleLDAPAuthenticationManagerConfiguration.FACTORY, - ExternalAuthenticationManager.ExternalAuthenticationManagerConfiguration.FACTORY - )) - { - _configPlugins.put(configFactory.getParentPaths(), configFactory); - } - for (SlowConsumerPolicyPluginFactory pluginFactory : Arrays.asList( - new TopicDeletePolicy.TopicDeletePolicyFactory())) - { - _policyPlugins.put(pluginFactory.getPluginName(), pluginFactory); - } - for (VirtualHostPluginFactory pluginFactory : Arrays.asList( - new SlowConsumerDetection.SlowConsumerFactory())) - { - _vhostPlugins.put(pluginFactory.getClass().getName(), pluginFactory); - } - - for (AuthenticationManagerPluginFactory pluginFactory : Arrays.asList( - PrincipalDatabaseAuthenticationManager.FACTORY, AnonymousAuthenticationManager.FACTORY, - KerberosAuthenticationManager.FACTORY, SimpleLDAPAuthenticationManager.FACTORY, - ExternalAuthenticationManager.FACTORY)) - { - _authenticationManagerPlugins.put(pluginFactory.getPluginName(), pluginFactory); - } - - if(bundleContext == null) - { - // Check the plugin directory path is set and exist - if (pluginPath == null) - { - _logger.info("No plugin path specified, no plugins will be loaded."); - return; - } - File pluginDir = new File(pluginPath); - if (!pluginDir.exists()) - { - _logger.warn("Plugin dir : " + pluginDir + " does not exist."); - return; - } - - // Add the bundle provided service interface package and the core OSGi - // packages to be exported from the class path via the system bundle. - - // Setup OSGi configuration property map - final StringMap configMap = new StringMap(false); - configMap.put(FRAMEWORK_SYSTEMPACKAGES, OSGI_SYSTEM_PACKAGES); - - // No automatic shutdown hook - configMap.put("felix.shutdown.hook", "false"); - - // Add system activator - List activators = new ArrayList(); - _activator = new Activator(); - activators.add(_activator); - configMap.put(SYSTEMBUNDLE_ACTIVATORS_PROP, activators); - - if (cachePath != null) - { - File cacheDir = new File(cachePath); - if (!cacheDir.exists() && cacheDir.canWrite()) - { - _logger.info("Creating plugin cache directory: " + cachePath); - cacheDir.mkdir(); - } - - // Set plugin cache directory and empty it - _logger.info("Cache bundles in directory " + cachePath); - configMap.put(FRAMEWORK_STORAGE, cachePath); - } - configMap.put(FRAMEWORK_STORAGE_CLEAN, FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT); - - // Set directory with plugins to auto-deploy - _logger.info("Auto deploying bundles from directory " + pluginPath); - configMap.put(AUTO_DEPLOY_DIR_PROPERY, pluginPath); - configMap.put(AUTO_DEPLOY_ACTION_PROPERY, AUTO_DEPLOY_INSTALL_VALUE + "," + AUTO_DEPLOY_START_VALUE); - - // Start plugin manager - _felix = new Felix(configMap); - try - { - _logger.info("Starting plugin manager framework"); - _felix.init(); - process(configMap, _felix.getBundleContext()); - _felix.start(); - _logger.info("Started plugin manager framework"); - } - catch (BundleException e) - { - throw new ConfigurationException("Could not start plugin manager: " + e.getMessage(), e); - } - - bundleContext = _activator.getContext(); - } - else - { - _logger.info("Using the specified external BundleContext"); - } - - _exchangeTracker = new ServiceTracker(bundleContext, ExchangeType.class.getName(), null); - _exchangeTracker.open(); - _trackers.add(_exchangeTracker); - - _securityTracker = new ServiceTracker(bundleContext, SecurityPluginFactory.class.getName(), null); - _securityTracker.open(); - _trackers.add(_securityTracker); - - _configTracker = new ServiceTracker(bundleContext, ConfigurationPluginFactory.class.getName(), null); - _configTracker.open(); - _trackers.add(_configTracker); - - _virtualHostTracker = new ServiceTracker(bundleContext, VirtualHostPluginFactory.class.getName(), null); - _virtualHostTracker.open(); - _trackers.add(_virtualHostTracker); - - _policyTracker = new ServiceTracker(bundleContext, SlowConsumerPolicyPluginFactory.class.getName(), null); - _policyTracker.open(); - _trackers.add(_policyTracker); - - _authenticationManagerTracker = new ServiceTracker(bundleContext, AuthenticationManagerPluginFactory.class.getName(), null); - _authenticationManagerTracker.open(); - _trackers.add(_authenticationManagerTracker); - - _logger.info("Opened service trackers"); - } - - private static Map getServices(ServiceTracker tracker) - { - Map services = new HashMap(); - - if ((tracker != null) && (tracker.getServices() != null)) - { - for (Object service : tracker.getServices()) - { - if (service instanceof PluginFactory) - { - services.put(((PluginFactory) service).getPluginName(), (T) service); - } - else - { - services.put(service.getClass().getName(), (T) service); - } - } - } - - return services; - } - - public static Map getServices(ServiceTracker tracker, Map plugins) - { - Map services = getServices(tracker); - services.putAll(plugins); - return services; - } - - public Map, ConfigurationPluginFactory> getConfigurationPlugins() - { - Map, ConfigurationPluginFactory> services = new IdentityHashMap, ConfigurationPluginFactory>(); - - if (_configTracker != null && _configTracker.getServices() != null) - { - for (Object service : _configTracker.getServices()) - { - ConfigurationPluginFactory factory = (ConfigurationPluginFactory) service; - services.put(factory.getParentPaths(), factory); - } - } - - services.putAll(_configPlugins); - - return services; - } - - public Map getVirtualHostPlugins() - { - return getServices(_virtualHostTracker, _vhostPlugins); - } - - public Map getSlowConsumerPlugins() - { - return getServices(_policyTracker, _policyPlugins); - } - - public Map> getExchanges() - { - return getServices(_exchangeTracker); - } - - public Map getSecurityPlugins() - { - return getServices(_securityTracker, _securityPlugins); - } - - public Map> getAuthenticationManagerPlugins() - { - return getServices(_authenticationManagerTracker, _authenticationManagerPlugins); - } - - public void close() - { - try - { - // Close all bundle trackers - for(ServiceTracker tracker : _trackers) - { - tracker.close(); - } - } - finally - { - if (_felix != null) - { - _logger.info("Stopping plugin manager framework"); - try - { - // FIXME should be stopAndWait() but hangs VM, need upgrade in felix - _felix.stop(); - } - catch (BundleException e) - { - // Ignore - } - - try - { - _felix.waitForStop(FELIX_STOP_TIMEOUT); - } - catch (InterruptedException e) - { - // Ignore - } - _logger.info("Stopped plugin manager framework"); - } - else - { - _logger.info("Plugin manager was started with an external BundleContext, " + - "skipping remaining shutdown tasks"); - } - } - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index 1e649c3cb7..ee1ef2418a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -29,11 +29,11 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -52,10 +52,7 @@ import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; import org.apache.qpid.protocol.ServerProtocolEngine; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.ConnectionConfig; -import org.apache.qpid.server.configuration.ConnectionConfigType; +import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.handler.ServerMethodDispatcherImpl; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; @@ -64,10 +61,11 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.ManagementActor; import org.apache.qpid.server.logging.messages.ConnectionMessages; import org.apache.qpid.server.logging.subjects.ConnectionLogSubject; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.output.ProtocolOutputConverterRegistry; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import org.apache.qpid.server.state.AMQState; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.stats.StatisticsCounter; @@ -75,13 +73,12 @@ import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionImpl; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.network.NetworkConnection; import org.apache.qpid.util.BytesDataOutput; -public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSession, ConnectionConfig +public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSession { private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class); @@ -115,7 +112,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi private volatile boolean _closed; // maximum number of channels this session should have - private long _maxNoOfChannels = ApplicationRegistry.getInstance().getConfiguration().getMaxChannelCount(); + private long _maxNoOfChannels; /* AMQP Version for this session */ private ProtocolVersion _protocolVersion = ProtocolVersion.getLatestSupportedVersion(); @@ -142,8 +139,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi private long _maxFrameSize; private final AtomicBoolean _closing = new AtomicBoolean(false); - private final UUID _qmfId; - private final ConfigStore _configStore; private long _createTime = System.currentTimeMillis(); private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; @@ -156,23 +151,25 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi private boolean _blocking; private final Lock _receivedLock; + private AtomicLong _lastWriteTime = new AtomicLong(System.currentTimeMillis()); + private final Broker _broker; - public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkConnection network, final long connectionId) + + public AMQProtocolEngine(Broker broker, NetworkConnection network, final long connectionId) { + _broker = broker; + _maxNoOfChannels = (Integer)broker.getAttribute(Broker.SESSION_COUNT_LIMIT); _receivedLock = new ReentrantLock(); - _stateManager = new AMQStateManager(virtualHostRegistry, this); + _stateManager = new AMQStateManager(broker, this); _codecFactory = new AMQCodecFactory(true, this); setNetworkConnection(network); _connectionID = connectionId; - _actor = new AMQPConnectionActor(this, virtualHostRegistry.getApplicationRegistry().getRootMessageLogger()); + _actor = new AMQPConnectionActor(this, _broker.getRootMessageLogger()); _logSubject = new ConnectionLogSubject(this); - _configStore = virtualHostRegistry.getConfigStore(); - _qmfId = _configStore.createId(); - _actor.message(ConnectionMessages.OPEN(null, null, null, false, false, false)); initialiseStatistics(); @@ -309,9 +306,13 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi try { + long startTime = 0; + String frameToString = null; if (_logger.isDebugEnabled()) { - _logger.debug("Frame Received: " + frame); + startTime = System.currentTimeMillis(); + frameToString = frame.toString(); + _logger.debug("RECV: " + frame); } // Check that this channel is not closing @@ -346,6 +347,11 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi closeChannel(channelId); throw e; } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Frame handled in " + (System.currentTimeMillis() - startTime) + " ms. Frame: " + frameToString); + } } finally { @@ -367,7 +373,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi // This sets the protocol version (and hence framing classes) for this session. setProtocolVersion(pv); - String mechanisms = ApplicationRegistry.getInstance().getAuthenticationManager(getLocalAddress()).getMechanisms(); + String mechanisms = _broker.getSubjectCreator(getLocalAddress()).getMechanisms(); String locales = "en_US"; @@ -549,8 +555,17 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi final ByteBuffer buf = asByteBuffer(frame); _writtenBytes += buf.remaining(); + + if(_logger.isDebugEnabled()) + { + _logger.debug("SEND: " + frame); + } + _sender.send(buf); - _lastIoTime = System.currentTimeMillis(); + final long time = System.currentTimeMillis(); + _lastIoTime = time; + _lastWriteTime.set(time); + if(!_deferFlush) { _sender.flush(); @@ -749,7 +764,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi if (delay > 0) { _network.setMaxWriteIdle(delay); - _network.setMaxReadIdle((int) (ApplicationRegistry.getInstance().getConfiguration().getHeartBeatTimeout() * delay)); + _network.setMaxReadIdle(BrokerProperties.DEFAULT_HEART_BEAT_TIMEOUT_FACTOR * delay); } } @@ -796,8 +811,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi closeAllChannels(); - getConfigStore().removeConfiguredObject(this); - for (Task task : _taskList) { task.doTask(this); @@ -983,7 +996,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi _virtualHost.getConnectionRegistry().registerConnection(this); - _configStore.addConfiguredObject(this); } public void addSessionCloseTask(Task task) @@ -1017,7 +1029,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi public Principal getAuthorizedPrincipal() { - return _authorizedSubject == null ? null : _authorizedSubject.getPrincipals().iterator().next(); + return _authorizedSubject == null ? null : AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(_authorizedSubject); } public SocketAddress getRemoteAddress() @@ -1070,12 +1082,12 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi public void readerIdle() { - // Nothing + // TODO - enforce disconnect on lack of inbound data } public synchronized void writerIdle() { - _sender.send(asByteBuffer(HeartbeatBody.FRAME)); + writeFrame(HeartbeatBody.FRAME); } public void exception(Throwable throwable) @@ -1185,32 +1197,11 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi return null; } - public ConfigStore getConfigStore() - { - return _configStore; - } - - public ConnectionConfigType getConfigType() - { - return ConnectionConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return getVirtualHost(); - } - public boolean isDurable() { return false; } - @Override - public UUID getQMFId() - { - return _qmfId; - } - public long getConnectionId() { return getSessionID(); @@ -1494,4 +1485,16 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi { return _receivedLock; } + + @Override + public long getLastReadTime() + { + return _lastReceivedTime; + } + + @Override + public long getLastWriteTime() + { + return _lastWriteTime.get(); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java index a8f62b0fa2..9d9bbe807b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java @@ -36,8 +36,7 @@ import org.apache.qpid.server.queue.SimpleAMQQueue; */ public interface AMQSessionModel extends Comparable { - /** Unique session ID across entire broker*/ - public UUID getQMFId(); + public UUID getId(); public AMQConnectionModel getConnectionModel(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java index 5c92aa95b6..d9e5e1c473 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java @@ -28,7 +28,7 @@ import java.util.Set; import org.apache.log4j.Logger; import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.transport.ServerConnection; import org.apache.qpid.transport.ConnectionDelegate; import org.apache.qpid.transport.Sender; @@ -42,24 +42,24 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine private Set _supported; private String _fqdn; - private IApplicationRegistry _appRegistry; + private final Broker _broker; private NetworkConnection _network; private Sender _sender; private final AmqpProtocolVersion _defaultSupportedReply; private volatile ServerProtocolEngine _delegate = new SelfDelegateProtocolEngine(); - public MultiVersionProtocolEngine(final IApplicationRegistry appRegistry, + public MultiVersionProtocolEngine(final Broker broker, final Set supported, final AmqpProtocolVersion defaultSupportedReply, final long id, final NetworkConnection network) { - this(appRegistry, supported, defaultSupportedReply, id); + this(broker, supported, defaultSupportedReply, id); setNetworkConnection(network); } - public MultiVersionProtocolEngine(final IApplicationRegistry appRegistry, + public MultiVersionProtocolEngine(final Broker broker, final Set supported, final AmqpProtocolVersion defaultSupportedReply, final long id) @@ -71,7 +71,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine } _id = id; - _appRegistry = appRegistry; + _broker = broker; _supported = supported; _defaultSupportedReply = defaultSupportedReply; } @@ -217,6 +217,18 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine _sender = sender; } + @Override + public long getLastReadTime() + { + return _delegate.getLastReadTime(); + } + + @Override + public long getLastWriteTime() + { + return _delegate.getLastWriteTime(); + } + private static interface DelegateCreator { @@ -240,7 +252,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public ServerProtocolEngine getProtocolEngine() { - return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _network, _id); + return new AMQProtocolEngine(_broker, _network, _id); } }; @@ -260,7 +272,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public ServerProtocolEngine getProtocolEngine() { - return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _network, _id); + return new AMQProtocolEngine(_broker, _network, _id); } }; @@ -280,7 +292,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public ServerProtocolEngine getProtocolEngine() { - return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _network, _id); + return new AMQProtocolEngine(_broker, _network, _id); } }; @@ -301,13 +313,15 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public ServerProtocolEngine getProtocolEngine() { - final ConnectionDelegate connDelegate = - new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn, _appRegistry.getAuthenticationManager(getLocalAddress())); + final ConnectionDelegate connDelegate = new org.apache.qpid.server.transport.ServerConnectionDelegate(_broker, + _fqdn, _broker.getSubjectCreator(getLocalAddress())); ServerConnection conn = new ServerConnection(_id); - conn.setConnectionDelegate(connDelegate); - return new ProtocolEngine_0_10( conn, _network, _appRegistry); + conn.setConnectionDelegate(connDelegate); + conn.setRemoteAddress(_network.getRemoteAddress()); + conn.setLocalAddress(_network.getLocalAddress()); + return new ProtocolEngine_0_10( conn, _network); } }; @@ -327,7 +341,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public ServerProtocolEngine getProtocolEngine() { - return new ProtocolEngine_1_0_0(_appRegistry,_id); + return new ProtocolEngine_1_0_0(_network, _broker, _id); } }; @@ -347,7 +361,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public ServerProtocolEngine getProtocolEngine() { - return new ProtocolEngine_1_0_0_SASL(_network, _appRegistry, _id); + return new ProtocolEngine_1_0_0_SASL(_network, _broker, _id); } }; @@ -407,6 +421,18 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine } + @Override + public long getLastReadTime() + { + return 0; + } + + @Override + public long getLastWriteTime() + { + return 0; + } + public long getConnectionId() { return _id; @@ -547,7 +573,29 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public void closed() { - + try + { + _delegate = new ClosedDelegateProtocolEngine(); + if(_logger.isDebugEnabled()) + { + _logger.debug("Connection from " + getRemoteAddress() + " was closed before any protocol version was established."); + } + } + catch(Exception e) + { + //ignore + } + finally + { + try + { + _network.close(); + } + catch(Exception e) + { + //ignore + } + } } public void writerIdle() @@ -564,5 +612,17 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine { } + + @Override + public long getLastReadTime() + { + return 0; + } + + @Override + public long getLastWriteTime() + { + return 0; + } } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java index 552b1c7054..9f078c8999 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java @@ -22,8 +22,7 @@ package org.apache.qpid.server.protocol; import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.model.Broker; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; @@ -32,11 +31,12 @@ public class MultiVersionProtocolEngineFactory implements ProtocolEngineFactory { private static final AtomicLong ID_GENERATOR = new AtomicLong(0); - private final IApplicationRegistry _appRegistry; + private final Broker _broker; private final Set _supported; private final AmqpProtocolVersion _defaultSupportedReply; - public MultiVersionProtocolEngineFactory(final Set supportedVersions, final AmqpProtocolVersion defaultSupportedReply) + public MultiVersionProtocolEngineFactory(Broker broker, + final Set supportedVersions, final AmqpProtocolVersion defaultSupportedReply) { if(defaultSupportedReply != null && !supportedVersions.contains(defaultSupportedReply)) { @@ -44,14 +44,14 @@ public class MultiVersionProtocolEngineFactory implements ProtocolEngineFactory + ") to an unsupported protocol version initiation is itself not supported!"); } - _appRegistry = ApplicationRegistry.getInstance(); + _broker = broker; _supported = supportedVersions; _defaultSupportedReply = defaultSupportedReply; } public ServerProtocolEngine newProtocolEngine() { - return new MultiVersionProtocolEngine(_appRegistry, _supported, _defaultSupportedReply, ID_GENERATOR.getAndIncrement()); + return new MultiVersionProtocolEngine(_broker, _supported, _defaultSupportedReply, ID_GENERATOR.getAndIncrement()); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java index fd6e9300ec..d5f7fe486c 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java @@ -21,13 +21,7 @@ package org.apache.qpid.server.protocol; import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.ConnectionConfig; -import org.apache.qpid.server.configuration.ConnectionConfigType; -import org.apache.qpid.server.configuration.VirtualHostConfig; import org.apache.qpid.server.logging.messages.ConnectionMessages; -import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.transport.ServerConnection; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.Assembler; @@ -37,9 +31,9 @@ import org.apache.qpid.transport.network.NetworkConnection; import java.net.SocketAddress; import java.nio.ByteBuffer; -import java.util.UUID; -public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocolEngine, ConnectionConfig + +public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocolEngine { public static final int MAX_FRAME_SIZE = 64 * 1024 - 1; @@ -47,20 +41,17 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol private long _readBytes; private long _writtenBytes; private ServerConnection _connection; - private final UUID _qmfId; - private final IApplicationRegistry _appRegistry; + private long _createTime = System.currentTimeMillis(); + private long _lastReadTime; + private long _lastWriteTime; public ProtocolEngine_0_10(ServerConnection conn, - NetworkConnection network, - final IApplicationRegistry appRegistry) + NetworkConnection network) { super(new Assembler(conn)); _connection = conn; - _connection.setConnectionConfig(this); - _qmfId = appRegistry.getConfigStore().createId(); - _appRegistry = appRegistry; if(network != null) { @@ -68,14 +59,6 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol } - _connection.onOpen(new Runnable() - { - public void run() - { - getConfigStore().addConfiguredObject(ProtocolEngine_0_10.this); - } - }); - } public void setNetworkConnection(NetworkConnection network) @@ -87,13 +70,61 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol { _network = network; - _connection.setSender(new Disassembler(sender, MAX_FRAME_SIZE)); + _connection.setNetworkConnection(network); + _connection.setSender(new Disassembler(wrapSender(sender), MAX_FRAME_SIZE)); _connection.setPeerPrincipal(_network.getPeerPrincipal()); // FIXME Two log messages to maintain compatibility with earlier protocol versions _connection.getLogActor().message(ConnectionMessages.OPEN(null, null, null, false, false, false)); _connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", null, false, true, false)); } + private Sender wrapSender(final Sender sender) + { + return new Sender() + { + @Override + public void setIdleTimeout(int i) + { + sender.setIdleTimeout(i); + + } + + @Override + public void send(ByteBuffer msg) + { + _lastWriteTime = System.currentTimeMillis(); + sender.send(msg); + + } + + @Override + public void flush() + { + sender.flush(); + + } + + @Override + public void close() + { + sender.close(); + + } + }; + } + + @Override + public long getLastReadTime() + { + return _lastReadTime; + } + + @Override + public long getLastWriteTime() + { + return _lastWriteTime; + } + public SocketAddress getRemoteAddress() { return _network.getRemoteAddress(); @@ -106,6 +137,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol public void received(final ByteBuffer buf) { + _lastReadTime = System.currentTimeMillis(); super.received(buf); _connection.receivedComplete(); } @@ -122,7 +154,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol public void writerIdle() { - //Todo + _connection.doHeartbeat(); } public void readerIdle() @@ -130,72 +162,16 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol //Todo } - public VirtualHostConfig getVirtualHost() - { - return _connection.getVirtualHost(); - } - public String getAddress() { return getRemoteAddress().toString(); } - public Boolean isIncoming() - { - return true; - } - - public Boolean isSystemConnection() - { - return false; - } - - public Boolean isFederationLink() - { - return false; - } - public String getAuthId() { return _connection.getAuthorizedPrincipal() == null ? null : _connection.getAuthorizedPrincipal().getName(); } - public String getRemoteProcessName() - { - return null; - } - - public Integer getRemotePID() - { - return null; - } - - public Integer getRemoteParentPID() - { - return null; - } - - public ConfigStore getConfigStore() - { - return _appRegistry.getConfigStore(); - } - - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public ConnectionConfigType getConfigType() - { - return ConnectionConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return getVirtualHost(); - } - public boolean isDurable() { return false; @@ -205,7 +181,6 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol public void closed() { super.closed(); - getConfigStore().removeConfiguredObject(this); } public long getCreateTime() @@ -213,16 +188,6 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol return _createTime; } - public Boolean isShadow() - { - return false; - } - - public void mgmtClose() - { - _connection.mgmtClose(); - } - public long getConnectionId() { return _connection.getConnectionId(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java index e6282315c6..f6b8e1e5c9 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.protocol; import java.net.SocketAddress; import java.nio.ByteBuffer; -import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import java.util.logging.Logger; @@ -39,11 +38,10 @@ import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler; import org.apache.qpid.amqp_1_0.type.Binary; import org.apache.qpid.amqp_1_0.type.FrameBody; import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConnectionConfigType; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.protocol.v1_0.Connection_1_0; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.NetworkConnection; @@ -54,8 +52,9 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa //private NetworkConnection _networkDriver; private long _readBytes; private long _writtenBytes; - private final UUID _id; - private final IApplicationRegistry _appRegistry; + private long _lastReadTime; + private long _lastWriteTime; + private final Broker _broker; private long _createTime = System.currentTimeMillis(); private ConnectionEndpoint _conn; private final long _connectionId; @@ -99,11 +98,14 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa - public ProtocolEngine_1_0_0(final IApplicationRegistry appRegistry, long id) + public ProtocolEngine_1_0_0(final NetworkConnection networkDriver, final Broker broker, long id) { - _id = appRegistry.getConfigStore().createId(); - _appRegistry = appRegistry; + _broker = broker; _connectionId = id; + if(networkDriver != null) + { + setNetworkConnection(networkDriver, networkDriver.getSender()); + } } @@ -142,13 +144,15 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa _network = network; _sender = sender; - Container container = new Container(_appRegistry.getBrokerId().toString()); + Container container = new Container(_broker.getId().toString()); + + VirtualHost virtualHost = _broker.getVirtualHostRegistry().getVirtualHost((String)_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)); - _conn = new ConnectionEndpoint(container, asSaslServerProvider(_appRegistry.getAuthenticationManager( + _conn = new ConnectionEndpoint(container, asSaslServerProvider(_broker.getSubjectCreator( getLocalAddress()))); - _conn.setConnectionEventListener(new Connection_1_0(_appRegistry, _conn, _connectionId)); - _conn.setFrameOutputHandler(this); _conn.setRemoteAddress(_network.getRemoteAddress()); + _conn.setConnectionEventListener(new Connection_1_0(virtualHost, _conn, _connectionId)); + _conn.setFrameOutputHandler(this); _frameWriter = new FrameWriter(_conn.getDescribedTypeRegistry()); _frameHandler = new FrameHandler(_conn); @@ -157,14 +161,14 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa _sender.flush(); } - private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager) + private SaslServerProvider asSaslServerProvider(final SubjectCreator subjectCreator) { return new SaslServerProvider() { @Override public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException { - return authenticationManager.createSaslServer(mechanism, fqdn, null); + return subjectCreator.createSaslServer(mechanism, fqdn, null); } }; } @@ -174,22 +178,6 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa return getRemoteAddress().toString(); } - - public ConfigStore getConfigStore() - { - return _appRegistry.getConfigStore(); - } - - public UUID getId() - { - return _id; - } - - public ConnectionConfigType getConfigType() - { - return ConnectionConfigType.getInstance(); - } - public boolean isDurable() { return false; @@ -197,6 +185,7 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa public synchronized void received(ByteBuffer msg) { + _lastReadTime = System.currentTimeMillis(); if(RAW_LOGGER.isLoggable(Level.FINE)) { ByteBuffer dup = msg.duplicate(); @@ -339,6 +328,7 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa synchronized(_sendLock) { + _lastWriteTime = System.currentTimeMillis(); if(FRAME_LOGGER.isLoggable(Level.FINE)) { FRAME_LOGGER.fine("SEND[" + getRemoteAddress() + "|" + amqFrame.getChannel() + "] : " + amqFrame.getFrameBody()); @@ -393,4 +383,13 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa return _connectionId; } + public long getLastReadTime() + { + return _lastReadTime; + } + + public long getLastWriteTime() + { + return _lastWriteTime; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java index a48441bf30..3b02ef2e5b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.protocol; import java.io.PrintWriter; import java.net.SocketAddress; import java.nio.ByteBuffer; -import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import javax.security.sasl.SaslException; @@ -40,12 +39,10 @@ import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler; import org.apache.qpid.amqp_1_0.type.Binary; import org.apache.qpid.amqp_1_0.type.FrameBody; import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConnectionConfigType; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.protocol.v1_0.Connection_1_0; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.NetworkConnection; @@ -53,8 +50,10 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut { private long _readBytes; private long _writtenBytes; - private final UUID _id; - private final IApplicationRegistry _appRegistry; + + private long _lastReadTime; + private long _lastWriteTime; + private final Broker _broker; private long _createTime = System.currentTimeMillis(); private ConnectionEndpoint _conn; private long _connectionId; @@ -113,13 +112,11 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut private State _state = State.A; - public ProtocolEngine_1_0_0_SASL(final NetworkConnection networkDriver, final IApplicationRegistry appRegistry, + public ProtocolEngine_1_0_0_SASL(final NetworkConnection networkDriver, final Broker broker, long id) { - _id = appRegistry.getConfigStore().createId(); _connectionId = id; - _appRegistry = appRegistry; - + _broker = broker; if(networkDriver != null) { setNetworkConnection(networkDriver, networkDriver.getSender()); @@ -162,21 +159,17 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut _network = network; _sender = sender; - Container container = new Container(_appRegistry.getBrokerId().toString()); + Container container = new Container(_broker.getId().toString()); - _conn = new ConnectionEndpoint(container, asSaslServerProvider(ApplicationRegistry.getInstance() - .getAuthenticationManager(getLocalAddress()))); - _conn.setConnectionEventListener(new Connection_1_0(_appRegistry, _conn, _connectionId)); + VirtualHost virtualHost = _broker.getVirtualHostRegistry().getVirtualHost((String)_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)); + _conn = new ConnectionEndpoint(container, asSaslServerProvider(_broker.getSubjectCreator(getLocalAddress()))); _conn.setRemoteAddress(getRemoteAddress()); - - + _conn.setConnectionEventListener(new Connection_1_0(virtualHost, _conn, _connectionId)); _conn.setFrameOutputHandler(this); _conn.setSaslFrameOutput(this); _conn.setOnSaslComplete(new Runnable() { - - public void run() { if(_conn.isAuthenticated()) @@ -201,14 +194,14 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut } - private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager) + private SaslServerProvider asSaslServerProvider(final SubjectCreator subjectCreator) { return new SaslServerProvider() { @Override public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException { - return authenticationManager.createSaslServer(mechanism, fqdn, null); + return subjectCreator.createSaslServer(mechanism, fqdn, null); } }; } @@ -218,22 +211,6 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut return getRemoteAddress().toString(); } - - public ConfigStore getConfigStore() - { - return _appRegistry.getConfigStore(); - } - - public UUID getId() - { - return _id; - } - - public ConnectionConfigType getConfigType() - { - return ConnectionConfigType.getInstance(); - } - public boolean isDurable() { return false; @@ -244,6 +221,7 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut public synchronized void received(ByteBuffer msg) { + _lastReadTime = System.currentTimeMillis(); if(RAW_LOGGER.isLoggable(Level.FINE)) { ByteBuffer dup = msg.duplicate(); @@ -386,17 +364,14 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut synchronized(_sendLock) { - + _lastWriteTime = System.currentTimeMillis(); if(FRAME_LOGGER.isLoggable(Level.FINE)) { FRAME_LOGGER.fine("SEND[" + getRemoteAddress() + "|" + amqFrame.getChannel() + "] : " + amqFrame.getFrameBody()); } - _frameWriter.setValue(amqFrame); - - ByteBuffer dup = ByteBuffer.allocate(_conn.getMaxFrameSize()); int size = _frameWriter.writeToBuffer(dup); @@ -447,4 +422,13 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut return _connectionId; } + public long getLastReadTime() + { + return _lastReadTime; + } + + public long getLastWriteTime() + { + return _lastWriteTime; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java index f429d8ba9f..cf4164c244 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java @@ -31,7 +31,6 @@ import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -44,7 +43,6 @@ import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTIO public class Connection_1_0 implements ConnectionEventListener { - private IApplicationRegistry _appRegistry; private VirtualHost _vhost; private final ConnectionEndpoint _conn; private final long _connectionId; @@ -62,10 +60,9 @@ public class Connection_1_0 implements ConnectionEventListener - public Connection_1_0(IApplicationRegistry appRegistry, ConnectionEndpoint conn, long connectionId) + public Connection_1_0(VirtualHost virtualHost, ConnectionEndpoint conn, long connectionId) { - _appRegistry = appRegistry; - _vhost = _appRegistry.getVirtualHostRegistry().getDefaultVirtualHost(); + _vhost = virtualHost; _conn = conn; _connectionId = connectionId; _vhost.getConnectionRegistry().registerConnection(_model); @@ -74,7 +71,7 @@ public class Connection_1_0 implements ConnectionEventListener public void remoteSessionCreation(SessionEndpoint endpoint) { - Session_1_0 session = new Session_1_0(_vhost, _appRegistry, this); + Session_1_0 session = new Session_1_0(_vhost, this); _sessions.add(session); endpoint.setSessionEventListener(session); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java index ba1a1ca45c..2cef27267b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java @@ -80,7 +80,7 @@ public class ExchangeDestination implements ReceivingDestination, SendingDestina { // NO-OP } - }, System.currentTimeMillis()); + }); return ACCEPTED; } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java index 140a815f57..fbce1666b7 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java @@ -23,9 +23,10 @@ package org.apache.qpid.server.protocol.v1_0; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.SessionConfig; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.MessageMetaData_1_0; import org.apache.qpid.server.message.MessageReference; @@ -34,11 +35,45 @@ import org.apache.qpid.server.store.StoredMessage; public class Message_1_0 implements ServerMessage, InboundMessage { + + + private static final AtomicIntegerFieldUpdater _refCountUpdater = + AtomicIntegerFieldUpdater.newUpdater(Message_1_0.class, "_referenceCount"); + + private volatile int _referenceCount = 0; + private final StoredMessage _storedMessage; private List _fragments; private WeakReference _session; + public Message_1_0(final StoredMessage storedMessage) + { + _storedMessage = storedMessage; + _session = null; + _fragments = restoreFragments(storedMessage); + } + + private static List restoreFragments(StoredMessage storedMessage) + { + ArrayList fragments = new ArrayList(); + final int FRAGMENT_SIZE = 2048; + int offset = 0; + ByteBuffer b; + do + { + + b = storedMessage.getContent(offset,FRAGMENT_SIZE); + if(b.hasRemaining()) + { + fragments.add(b); + offset+= b.remaining(); + } + } + while(b.hasRemaining()); + return fragments; + } + public Message_1_0(final StoredMessage storedMessage, final List fragments, final Session_1_0 session) @@ -136,11 +171,6 @@ public class Message_1_0 implements ServerMessage, InboundMessage return buf; } - public SessionConfig getSessionConfig() - { - return null; //TODO - } - public List getFragments() { return _fragments; @@ -148,7 +178,61 @@ public class Message_1_0 implements ServerMessage, InboundMessage public Session_1_0 getSession() { - return _session.get(); + return _session == null ? null : _session.get(); + } + + + public boolean incrementReference() + { + if(_refCountUpdater.incrementAndGet(this) <= 0) + { + _refCountUpdater.decrementAndGet(this); + return false; + } + else + { + return true; + } + } + + /** + * Threadsafe. This will decrement the reference count and when it reaches zero will remove the message from the + * message store. + * + * + * @throws org.apache.qpid.server.queue.MessageCleanupException when an attempt was made to remove the message from the message store and that + * failed + */ + public void decrementReference() + { + int count = _refCountUpdater.decrementAndGet(this); + + // note that the operation of decrementing the reference count and then removing the message does not + // have to be atomic since the ref count starts at 1 and the exchange itself decrements that after + // the message has been passed to all queues. i.e. we are + // not relying on the all the increments having taken place before the delivery manager decrements. + if (count == 0) + { + // set the reference count way below 0 so that we can detect that the message has been deleted + // this is to guard against the message being spontaneously recreated (from the mgmt console) + // by copying from other queues at the same time as it is being removed. + _refCountUpdater.set(this,Integer.MIN_VALUE/2); + + // must check if the handle is null since there may be cases where we decide to throw away a message + // and the handle has not yet been constructed + if (_storedMessage != null) + { + _storedMessage.remove(); + } + } + else + { + if (count < 0) + { + throw new RuntimeException("Reference count for message id " + getMessageNumber() + + " has gone below 0."); + } + } } public static class Reference extends MessageReference @@ -160,13 +244,13 @@ public class Message_1_0 implements ServerMessage, InboundMessage protected void onReference(Message_1_0 message) { - + message.incrementReference(); } protected void onRelease(Message_1_0 message) { - + message.decrementReference(); } -} + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java index 999ffc55e5..a0ed824c58 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java @@ -36,7 +36,6 @@ import org.apache.qpid.amqp_1_0.type.transport.*; import org.apache.qpid.amqp_1_0.type.transport.Error; import org.apache.qpid.AMQException; import org.apache.qpid.AMQSecurityException; -import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.message.InboundMessage; @@ -45,8 +44,6 @@ import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.transport.ServerConnection; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -58,7 +55,6 @@ import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_F public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSubject { private static final Symbol LIFETIME_POLICY = Symbol.valueOf("lifetime-policy"); - private IApplicationRegistry _appRegistry; private VirtualHost _vhost; private AutoCommitTransaction _transaction; @@ -68,9 +64,8 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu private UUID _id = UUID.randomUUID(); - public Session_1_0(VirtualHost vhost, IApplicationRegistry appRegistry, final Connection_1_0 connection) + public Session_1_0(VirtualHost vhost, final Connection_1_0 connection) { - _appRegistry = appRegistry; _vhost = vhost; _transaction = new AutoCommitTransaction(vhost.getMessageStore()); _connection = connection; @@ -456,8 +451,9 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu { } + @Override - public UUID getQMFId() + public UUID getId() { return _id; } @@ -580,13 +576,6 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu return 0; } - @Override - public int compareTo(AMQSessionModel o) - { - return getQMFId().compareTo(o.getQMFId()); - } - - public String toLogString() { @@ -604,4 +593,9 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu + "] "; } + @Override + public int compareTo(AMQSessionModel o) + { + return getId().compareTo(o.getId()); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java index d3efd63ee0..4f610cc925 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java @@ -23,8 +23,7 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.QueueConfig; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeReferrer; import org.apache.qpid.server.logging.LogSubject; @@ -39,9 +38,10 @@ import java.util.List; import java.util.Map; import java.util.Set; -public interface AMQQueue extends Comparable, ExchangeReferrer, TransactionLogResource, BaseQueue, - QueueConfig +public interface AMQQueue extends Comparable, ExchangeReferrer, TransactionLogResource, BaseQueue { + String getName(); + public interface NotificationListener { void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg); @@ -277,9 +277,7 @@ public interface AMQQueue extends Comparable, ExchangeReferrer, Transa public void doTask(AMQQueue queue) throws AMQException; } - void configure(ConfigurationPlugin config); - - ConfigurationPlugin getConfiguration(); + void configure(QueueConfiguration config); void setExclusive(boolean exclusive); @@ -315,4 +313,18 @@ public interface AMQQueue extends Comparable, ExchangeReferrer, Transa */ String getDescription(); + long getPersistentByteDequeues(); + + long getPersistentMsgDequeues(); + + long getPersistentByteEnqueues(); + + long getPersistentMsgEnqueues(); + + long getTotalDequeueSize(); + + long getTotalEnqueueSize(); + + long getUnackedMessageCount(); + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java index 3a18fae2ec..a65a6a8eb2 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java @@ -30,17 +30,25 @@ import org.apache.qpid.AMQSecurityException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.QueueConfiguration; -import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.exchange.DefaultExchangeFactory; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; public class AMQQueueFactory { + public static final String X_QPID_FLOW_RESUME_CAPACITY = "x-qpid-flow-resume-capacity"; + public static final String X_QPID_CAPACITY = "x-qpid-capacity"; + public static final String X_QPID_MINIMUM_ALERT_REPEAT_GAP = "x-qpid-minimum-alert-repeat-gap"; + public static final String X_QPID_MAXIMUM_MESSAGE_COUNT = "x-qpid-maximum-message-count"; + public static final String X_QPID_MAXIMUM_MESSAGE_SIZE = "x-qpid-maximum-message-size"; + public static final String X_QPID_MAXIMUM_MESSAGE_AGE = "x-qpid-maximum-message-age"; + public static final String X_QPID_MAXIMUM_QUEUE_DEPTH = "x-qpid-maximum-queue-depth"; + public static final String X_QPID_PRIORITIES = "x-qpid-priorities"; public static final String X_QPID_DESCRIPTION = "x-qpid-description"; public static final String QPID_LVQ_KEY = "qpid.LVQ_key"; @@ -119,42 +127,49 @@ public class AMQQueueFactory } private static final QueueProperty[] DECLAREABLE_PROPERTIES = { - new QueueLongProperty("x-qpid-maximum-message-age") + new QueueLongProperty(X_QPID_MAXIMUM_MESSAGE_AGE) { public void setPropertyValue(AMQQueue queue, long value) { queue.setMaximumMessageAge(value); } }, - new QueueLongProperty("x-qpid-maximum-message-size") + new QueueLongProperty(X_QPID_MAXIMUM_MESSAGE_SIZE) { public void setPropertyValue(AMQQueue queue, long value) { queue.setMaximumMessageSize(value); } }, - new QueueLongProperty("x-qpid-maximum-message-count") + new QueueLongProperty(X_QPID_MAXIMUM_MESSAGE_COUNT) { public void setPropertyValue(AMQQueue queue, long value) { queue.setMaximumMessageCount(value); } }, - new QueueLongProperty("x-qpid-minimum-alert-repeat-gap") + new QueueLongProperty(X_QPID_MAXIMUM_QUEUE_DEPTH) + { + public void setPropertyValue(AMQQueue queue, long value) + { + queue.setMaximumQueueDepth(value); + } + }, + new QueueLongProperty(X_QPID_MINIMUM_ALERT_REPEAT_GAP) { public void setPropertyValue(AMQQueue queue, long value) { queue.setMinimumAlertRepeatGap(value); } }, - new QueueLongProperty("x-qpid-capacity") + new QueueLongProperty(X_QPID_CAPACITY) { public void setPropertyValue(AMQQueue queue, long value) { queue.setCapacity(value); } }, - new QueueLongProperty("x-qpid-flow-resume-capacity") + new QueueLongProperty(X_QPID_FLOW_RESUME_CAPACITY) { public void setPropertyValue(AMQQueue queue, long value) { @@ -411,9 +426,7 @@ public class AMQQueueFactory */ protected static String getDeadLetterQueueName(String name) { - ServerConfiguration serverConfig = ApplicationRegistry.getInstance().getConfiguration(); - String dlQueueName = name + serverConfig.getDeadLetterQueueSuffix(); - return dlQueueName; + return name + System.getProperty(BrokerProperties.PROPERTY_DEAD_LETTER_QUEUE_SUFFIX, DEFAULT_DLQ_NAME_SUFFIX); } /** @@ -425,9 +438,7 @@ public class AMQQueueFactory */ protected static String getDeadLetterExchangeName(String name) { - ServerConfiguration serverConfig = ApplicationRegistry.getInstance().getConfiguration(); - String dlExchangeName = name + serverConfig.getDeadLetterExchangeSuffix(); - return dlExchangeName; + return name + System.getProperty(BrokerProperties.PROPERTY_DEAD_LETTER_EXCHANGE_SUFFIX, DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); } private static Map createQueueArgumentsFromConfig(QueueConfiguration config) diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java index bbc33ca846..d7dbd58537 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java @@ -47,7 +47,7 @@ public class InboundMessageAdapter implements InboundMessage public AMQShortString getRoutingKeyShortString() { - return AMQShortString.valueOf(_entry.getMessage()); + return AMQShortString.valueOf(_entry.getMessage().getRoutingKey()); } public String getRoutingKey() diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java index c5a610c7b6..18affc7161 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java @@ -34,7 +34,6 @@ import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.MessageContentSource; import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.StoredMessage; import java.nio.ByteBuffer; @@ -47,9 +46,6 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes /** Used for debugging purposes. */ private static final Logger _logger = Logger.getLogger(IncomingMessage.class); - private static final boolean SYNCHED_CLOCKS = - ApplicationRegistry.getInstance().getConfiguration().getSynchedClocks(); - private final MessagePublishInfo _messagePublishInfo; private ContentHeaderBody _contentHeaderBody; @@ -101,33 +97,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes public void setExpiration() { - long expiration = - ((BasicContentHeaderProperties) _contentHeaderBody.getProperties()).getExpiration(); - long timestamp = - ((BasicContentHeaderProperties) _contentHeaderBody.getProperties()).getTimestamp(); - - if (SYNCHED_CLOCKS) - { - _expiration = expiration; - } - else - { - // Update TTL to be in broker time. - if (expiration != 0L) - { - if (timestamp != 0L) - { - // todo perhaps use arrival time - long diff = (System.currentTimeMillis() - timestamp); - - if ((diff > 1000L) || (diff < 1000L)) - { - _expiration = expiration + diff; - } - } - } - } - + _expiration = ((BasicContentHeaderProperties) _contentHeaderBody.getProperties()).getExpiration(); } public MessageMetaData headersReceived(long currentTime) diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java index 25e771a9cf..9aa8d1da83 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java @@ -454,7 +454,7 @@ public abstract class QueueEntryImpl implements QueueEntry { } - }, 0L); + }); txn.dequeue(currentQueue, message, new ServerTransaction.Action() { diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index d42bd6cf03..73c2870b9b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java @@ -41,11 +41,8 @@ import org.apache.qpid.AMQSecurityException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.pool.ReferenceCountingExecutorService; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.QueueConfigType; import org.apache.qpid.server.configuration.QueueConfiguration; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.plugins.AbstractConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; @@ -55,7 +52,6 @@ import org.apache.qpid.server.logging.messages.QueueMessages; import org.apache.qpid.server.logging.subjects.QueueLogSubject; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.security.AuthorizationHolder; import org.apache.qpid.server.subscription.AssignedSubscriptionMessageGroupManager; import org.apache.qpid.server.subscription.DefinedGroupMessageGroupManager; @@ -135,23 +131,23 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes private final AtomicInteger _bindingCountHigh = new AtomicInteger(); /** max allowed size(KB) of a single message */ - private long _maximumMessageSize = ApplicationRegistry.getInstance().getConfiguration().getMaximumMessageSize(); + private long _maximumMessageSize; /** max allowed number of messages on a queue. */ - private long _maximumMessageCount = ApplicationRegistry.getInstance().getConfiguration().getMaximumMessageCount(); + private long _maximumMessageCount; /** max queue depth for the queue */ - private long _maximumQueueDepth = ApplicationRegistry.getInstance().getConfiguration().getMaximumQueueDepth(); + private long _maximumQueueDepth; /** maximum message age before alerts occur */ - private long _maximumMessageAge = ApplicationRegistry.getInstance().getConfiguration().getMaximumMessageAge(); + private long _maximumMessageAge; /** the minimum interval between sending out consecutive alerts of the same type */ - private long _minimumAlertRepeatGap = ApplicationRegistry.getInstance().getConfiguration().getMinimumAlertRepeatGap(); + private long _minimumAlertRepeatGap; - private long _capacity = ApplicationRegistry.getInstance().getConfiguration().getCapacity(); + private long _capacity; - private long _flowResumeCapacity = ApplicationRegistry.getInstance().getConfiguration().getFlowResumeCapacity(); + private long _flowResumeCapacity; private final Set _notificationChecks = EnumSet.noneOf(NotificationCheck.class); @@ -185,11 +181,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes //TODO : persist creation time private long _createTime = System.currentTimeMillis(); - private UUID _qmfId; - private ConfigurationPlugin _queueConfiguration; + private AbstractConfiguration _queueConfiguration; /** the maximum delivery count for each message on this queue or 0 if maximum delivery count is not to be enforced. */ - private int _maximumDeliveryCount = ApplicationRegistry.getInstance().getConfiguration().getMaxDeliveryCount(); + private int _maximumDeliveryCount; private final MessageGroupManager _messageGroupManager; private final Collection _subscriptionListeners = @@ -243,7 +238,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes _arguments = arguments == null ? new HashMap() : new HashMap(arguments); _id = id; - _qmfId = getConfigStore().createId(); _asyncDelivery = ReferenceCountingExecutorService.getInstance().acquireExecutorService(); _logSubject = new QueueLogSubject(this); @@ -259,8 +253,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes durable, !durable, _entries.getPriorities() > 0)); - getConfigStore().addConfiguredObject(this); - if(arguments != null && arguments.containsKey(QPID_GROUP_HEADER_KEY)) { if(arguments.containsKey(QPID_SHARED_MSG_GROUP) && String.valueOf(arguments.get(QPID_SHARED_MSG_GROUP)).equals("1")) @@ -331,22 +323,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes return _id; } - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public QueueConfigType getConfigType() - { - return QueueConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return getVirtualHost(); - } - public boolean isDurable() { return _durable; @@ -621,24 +597,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes break; } } - - reconfigure(); - } - - private void reconfigure() - { - //Reconfigure the queue for to reflect this new binding. - ConfigurationPlugin config = getVirtualHost().getConfiguration().getQueueConfiguration(this); - - if (config != null) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Reconfiguring queue(" + this + ") with config:" + config + " was "+ _queueConfiguration); - } - // Reconfigure with new config. - configure(config); - } } public int getBindingCountHigh() @@ -649,8 +607,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes public void removeBinding(final Binding binding) { _bindings.remove(binding); - - reconfigure(); } public List getBindings() @@ -1383,7 +1339,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } _virtualHost.getQueueRegistry().unregisterQueue(_name); - getConfigStore().removeConfiguredObject(this); List entries = getMessagesOnTheQueue(new QueueEntryFilter() { @@ -1442,7 +1397,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { } - }, 0L); + }); txn.dequeue(this, entry.getMessage(), new ServerTransaction.Action() { @@ -2161,39 +2116,21 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } - public void configure(ConfigurationPlugin config) + public void configure(QueueConfiguration config) { if (config != null) { - if (config instanceof QueueConfiguration) - { - - setMaximumMessageAge(((QueueConfiguration)config).getMaximumMessageAge()); - setMaximumQueueDepth(((QueueConfiguration)config).getMaximumQueueDepth()); - setMaximumMessageSize(((QueueConfiguration)config).getMaximumMessageSize()); - setMaximumMessageCount(((QueueConfiguration)config).getMaximumMessageCount()); - setMinimumAlertRepeatGap(((QueueConfiguration)config).getMinimumAlertRepeatGap()); - setMaximumDeliveryCount(((QueueConfiguration)config).getMaxDeliveryCount()); - _capacity = ((QueueConfiguration)config).getCapacity(); - _flowResumeCapacity = ((QueueConfiguration)config).getFlowResumeCapacity(); - } - - _queueConfiguration = config; - + setMaximumMessageAge(config.getMaximumMessageAge()); + setMaximumQueueDepth(config.getMaximumQueueDepth()); + setMaximumMessageSize(config.getMaximumMessageSize()); + setMaximumMessageCount(config.getMaximumMessageCount()); + setMinimumAlertRepeatGap(config.getMinimumAlertRepeatGap()); + setMaximumDeliveryCount(config.getMaxDeliveryCount()); + _capacity = config.getCapacity(); + _flowResumeCapacity = config.getFlowResumeCapacity(); } } - - public ConfigurationPlugin getConfiguration() - { - return _queueConfiguration; - } - - public ConfigStore getConfigStore() - { - return getVirtualHost().getConfigStore(); - } - public long getMessageDequeueCount() { return _dequeueCount.get(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index e0e317f75d..1379b375cf 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -20,44 +20,39 @@ */ package org.apache.qpid.server.registry; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.server.logging.*; -import org.osgi.framework.BundleContext; +import java.util.Collection; +import java.util.Timer; +import java.util.TimerTask; +import org.apache.log4j.Logger; import org.apache.qpid.common.Closeable; import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.qmf.QMFService; -import org.apache.qpid.server.configuration.BrokerConfig; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfigurationManager; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.configuration.SystemConfig; -import org.apache.qpid.server.configuration.SystemConfigImpl; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.configuration.startup.DefaultRecovererProvider; +import org.apache.qpid.server.logging.CompositeStartupMessageLogger; +import org.apache.qpid.server.logging.Log4jMessageLogger; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.actors.AbstractActor; import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.GenericActor; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.logging.messages.VirtualHostMessages; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.adapter.BrokerAdapter; -import org.apache.qpid.server.plugins.PluginManager; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManagerRegistry; -import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.stats.StatisticsCounter; -import org.apache.qpid.server.transport.QpidAcceptor; +import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.*; -import java.util.concurrent.atomic.AtomicReference; - /** * An abstract application registry that provides access to configuration information and handles the @@ -65,321 +60,90 @@ import java.util.concurrent.atomic.AtomicReference; *

* Subclasses should handle the construction of the "registered objects" such as the exchange registry. */ -public abstract class ApplicationRegistry implements IApplicationRegistry +public class ApplicationRegistry implements IApplicationRegistry { - private static final Logger _logger = Logger.getLogger(ApplicationRegistry.class); - private static AtomicReference _instance = new AtomicReference(null); - - private final ServerConfiguration _configuration; - - private final Map _acceptors = - Collections.synchronizedMap(new HashMap()); - - private IAuthenticationManagerRegistry _authenticationManagerRegistry; - - private final VirtualHostRegistry _virtualHostRegistry = new VirtualHostRegistry(this); - - private SecurityManager _securityManager; + private final VirtualHostRegistry _virtualHostRegistry = new VirtualHostRegistry(); - private PluginManager _pluginManager; - - private ConfigurationManager _configurationManager; - - private RootMessageLogger _rootMessageLogger; - - private CompositeStartupMessageLogger _startupMessageLogger; - - private UUID _brokerId = UUID.randomUUID(); - - private QMFService _qmfService; - - private BrokerConfig _brokerConfig; + private volatile RootMessageLogger _rootMessageLogger; private Broker _broker; - private ConfigStore _configStore; - private Timer _reportingTimer; private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; - private BundleContext _bundleContext; - - private final List _portBindingListeners = new ArrayList(); - - private int _httpManagementPort = -1, _httpsManagementPort = -1; - private LogRecorder _logRecorder; - private List _authManagerChangeListeners = - new ArrayList(); - - public Map getAcceptors() - { - synchronized (_acceptors) - { - return new HashMap(_acceptors); - } - } - - protected void setSecurityManager(SecurityManager securityManager) - { - _securityManager = securityManager; - } - - protected void setPluginManager(PluginManager pluginManager) - { - _pluginManager = pluginManager; - } - - protected void setConfigurationManager(ConfigurationManager configurationManager) - { - _configurationManager = configurationManager; - } + private ConfigurationEntryStore _store; + private TaskExecutor _taskExecutor; protected void setRootMessageLogger(RootMessageLogger rootMessageLogger) { _rootMessageLogger = rootMessageLogger; } - protected CompositeStartupMessageLogger getStartupMessageLogger() - { - return _startupMessageLogger; - } - - protected void setStartupMessageLogger(CompositeStartupMessageLogger startupMessageLogger) + public ApplicationRegistry(ConfigurationEntryStore store) { - _startupMessageLogger = startupMessageLogger; - } - - protected void setBrokerId(UUID brokerId) - { - _brokerId = brokerId; - } - - protected QMFService getQmfService() - { - return _qmfService; - } - - protected void setQmfService(QMFService qmfService) - { - _qmfService = qmfService; - } - - public static void initialise(IApplicationRegistry instance) throws Exception - { - if(instance == null) - { - throw new IllegalArgumentException("ApplicationRegistry instance must not be null"); - } - - if(!_instance.compareAndSet(null, instance)) - { - throw new IllegalStateException("An ApplicationRegistry is already initialised"); - } - - _logger.info("Initialising Application Registry(" + instance + ")"); - - - final ConfigStore store = ConfigStore.newInstance(); - store.setRoot(new SystemConfigImpl(store)); - instance.setConfigStore(store); - - final BrokerConfig brokerConfig = new BrokerConfigAdapter(instance); - - final SystemConfig system = store.getRoot(); - system.addBroker(brokerConfig); - instance.setBrokerConfig(brokerConfig); - - try - { - instance.initialise(); - } - catch (Exception e) - { - _instance.set(null); - - //remove the Broker instance, then re-throw - try - { - system.removeBroker(brokerConfig); - } - catch(Throwable t) - { - //ignore - } - - throw e; - } - } - - public ConfigStore getConfigStore() - { - return _configStore; - } - - public void setConfigStore(final ConfigStore configStore) - { - _configStore = configStore; - } - - public static boolean isConfigured() - { - return _instance.get() != null; - } - - public static void remove() - { - IApplicationRegistry instance = _instance.getAndSet(null); - try - { - if (instance != null) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Shutting down ApplicationRegistry(" + instance + ")"); - } - instance.close(); - } - } - catch (Exception e) - { - _logger.error("Error shutting down Application Registry(" + instance + "): " + e, e); - } - } - - protected ApplicationRegistry(ServerConfiguration configuration) - { - this(configuration, null); - } - - protected ApplicationRegistry(ServerConfiguration configuration, BundleContext bundleContext) - { - _configuration = configuration; - _bundleContext = bundleContext; - } - - public void configure() throws ConfigurationException - { - _configurationManager = new ConfigurationManager(); - - try - { - _pluginManager = new PluginManager(_configuration.getPluginDirectory(), _configuration.getCacheDirectory(), _bundleContext); - } - catch (Exception e) - { - throw new ConfigurationException(e); - } - - _configuration.initialise(); + _store = store; + initialiseStatistics(); } public void initialise() throws Exception { + // Create the RootLogger to be used during broker operation + boolean statusUpdatesEnabled = Boolean.parseBoolean(System.getProperty(BrokerProperties.PROPERTY_STATUS_UPDATES, "true")); + _rootMessageLogger = new Log4jMessageLogger(statusUpdatesEnabled); + _logRecorder = new LogRecorder(); - //Create the RootLogger to be used during broker operation - _rootMessageLogger = new Log4jMessageLogger(_configuration); //Create the composite (log4j+SystemOut MessageLogger to be used during startup RootMessageLogger[] messageLoggers = {new SystemOutMessageLogger(), _rootMessageLogger}; - _startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers); + CompositeStartupMessageLogger startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers); - BrokerActor actor = new BrokerActor(_startupMessageLogger); - CurrentActor.setDefault(actor); + BrokerActor actor = new BrokerActor(startupMessageLogger); CurrentActor.set(actor); - + CurrentActor.setDefault(actor); + GenericActor.setDefaultMessageLogger(_rootMessageLogger); try { - initialiseStatistics(); - - if(_configuration.getHTTPManagementEnabled()) - { - _httpManagementPort = _configuration.getHTTPManagementPort(); - } - if (_configuration.getHTTPSManagementEnabled()) - { - _httpsManagementPort = _configuration.getHTTPSManagementPort(); - } - - _broker = new BrokerAdapter(this); - - configure(); - - _qmfService = new QMFService(getConfigStore(), this); - logStartupMessages(CurrentActor.get()); - _securityManager = new SecurityManager(_configuration, _pluginManager); + _taskExecutor = new TaskExecutor(); + _taskExecutor.start(); - _authenticationManagerRegistry = createAuthenticationManagerRegistry(_configuration, _pluginManager); + RecovererProvider provider = new DefaultRecovererProvider((StatisticsGatherer)this, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor); + ConfiguredObjectRecoverer brokerRecoverer = provider.getRecoverer(Broker.class.getSimpleName()); + _broker = (Broker) brokerRecoverer.create(provider, _store.getRootEntry()); - if(!_authManagerChangeListeners.isEmpty()) - { - for(IAuthenticationManagerRegistry.RegistryChangeListener listener : _authManagerChangeListeners) - { + _virtualHostRegistry.setDefaultVirtualHostName((String)_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)); - _authenticationManagerRegistry.addRegistryChangeListener(listener); - for(AuthenticationManager authMgr : _authenticationManagerRegistry.getAvailableAuthenticationManagers().values()) - { - listener.authenticationManagerRegistered(authMgr); - } - } - _authManagerChangeListeners.clear(); - } - } - finally - { - CurrentActor.remove(); - } - - CurrentActor.set(new BrokerActor(_rootMessageLogger)); - try - { - initialiseVirtualHosts(); initialiseStatisticsReporting(); + + // starting the broker + _broker.setDesiredState(State.INITIALISING, State.ACTIVE); + + CurrentActor.get().message(BrokerMessages.READY()); } finally { - // Startup complete, so pop the current actor CurrentActor.remove(); } - } - protected IAuthenticationManagerRegistry createAuthenticationManagerRegistry(ServerConfiguration _configuration, PluginManager _pluginManager) - throws ConfigurationException - { - return new AuthenticationManagerRegistry(_configuration, _pluginManager); + CurrentActor.setDefault(new BrokerActor(_rootMessageLogger)); } - protected void initialiseVirtualHosts() throws Exception + private void initialiseStatisticsReporting() { - for (String name : _configuration.getVirtualHosts()) - { - createVirtualHost(_configuration.getVirtualHostConfig(name)); - } - getVirtualHostRegistry().setDefaultVirtualHostName(_configuration.getDefaultVirtualHost()); - } - - public void initialiseStatisticsReporting() - { - long report = _configuration.getStatisticsReportingPeriod() * 1000; // convert to ms - final boolean broker = _configuration.isStatisticsGenerationBrokerEnabled(); - final boolean virtualhost = _configuration.isStatisticsGenerationVirtualhostsEnabled(); - final boolean reset = _configuration.isStatisticsReportResetEnabled(); + long report = ((Number)_broker.getAttribute(Broker.STATISTICS_REPORTING_PERIOD)).intValue() * 1000; // convert to ms + final boolean reset = (Boolean)_broker.getAttribute(Broker.STATISTICS_REPORTING_RESET_ENABLED); /* add a timer task to report statistics if generation is enabled for broker or virtualhosts */ - if (report > 0L && (broker || virtualhost)) + if (report > 0L) { _reportingTimer = new Timer("Statistics-Reporting", true); - - - - _reportingTimer.scheduleAtFixedRate(new StatisticsReportingTask(broker, virtualhost, reset), - report / 2, - report); + StatisticsReportingTask task = new StatisticsReportingTask(reset, _rootMessageLogger); + _reportingTimer.scheduleAtFixedRate(task, report / 2, report); } } @@ -388,76 +152,62 @@ public abstract class ApplicationRegistry implements IApplicationRegistry private final int DELIVERED = 0; private final int RECEIVED = 1; - private boolean _broker; - private boolean _virtualhost; - private boolean _reset; + private final boolean _reset; + private final RootMessageLogger _logger; - - public StatisticsReportingTask(boolean broker, boolean virtualhost, boolean reset) + public StatisticsReportingTask(boolean reset, RootMessageLogger logger) { - _broker = broker; - _virtualhost = virtualhost; _reset = reset; + _logger = logger; } public void run() { - CurrentActor.set(new AbstractActor(ApplicationRegistry.getInstance().getRootMessageLogger()) { + CurrentActor.set(new AbstractActor(_logger) + { public String getLogMessage() { return "[" + Thread.currentThread().getName() + "] "; } }); - - if (_broker) + try { CurrentActor.get().message(BrokerMessages.STATS_DATA(DELIVERED, _dataDelivered.getPeak() / 1024.0, _dataDelivered.getTotal())); CurrentActor.get().message(BrokerMessages.STATS_MSGS(DELIVERED, _messagesDelivered.getPeak(), _messagesDelivered.getTotal())); CurrentActor.get().message(BrokerMessages.STATS_DATA(RECEIVED, _dataReceived.getPeak() / 1024.0, _dataReceived.getTotal())); CurrentActor.get().message(BrokerMessages.STATS_MSGS(RECEIVED, _messagesReceived.getPeak(), _messagesReceived.getTotal())); - } + Collection hosts = _virtualHostRegistry.getVirtualHosts(); - if (_virtualhost) - { - for (VirtualHost vhost : getVirtualHostRegistry().getVirtualHosts()) + if (hosts.size() > 1) { - String name = vhost.getName(); - StatisticsCounter dataDelivered = vhost.getDataDeliveryStatistics(); - StatisticsCounter messagesDelivered = vhost.getMessageDeliveryStatistics(); - StatisticsCounter dataReceived = vhost.getDataReceiptStatistics(); - StatisticsCounter messagesReceived = vhost.getMessageReceiptStatistics(); - - CurrentActor.get().message(VirtualHostMessages.STATS_DATA(name, DELIVERED, dataDelivered.getPeak() / 1024.0, dataDelivered.getTotal())); - CurrentActor.get().message(VirtualHostMessages.STATS_MSGS(name, DELIVERED, messagesDelivered.getPeak(), messagesDelivered.getTotal())); - CurrentActor.get().message(VirtualHostMessages.STATS_DATA(name, RECEIVED, dataReceived.getPeak() / 1024.0, dataReceived.getTotal())); - CurrentActor.get().message(VirtualHostMessages.STATS_MSGS(name, RECEIVED, messagesReceived.getPeak(), messagesReceived.getTotal())); + for (VirtualHost vhost : hosts) + { + String name = vhost.getName(); + StatisticsCounter dataDelivered = vhost.getDataDeliveryStatistics(); + StatisticsCounter messagesDelivered = vhost.getMessageDeliveryStatistics(); + StatisticsCounter dataReceived = vhost.getDataReceiptStatistics(); + StatisticsCounter messagesReceived = vhost.getMessageReceiptStatistics(); + + CurrentActor.get().message(VirtualHostMessages.STATS_DATA(name, DELIVERED, dataDelivered.getPeak() / 1024.0, dataDelivered.getTotal())); + CurrentActor.get().message(VirtualHostMessages.STATS_MSGS(name, DELIVERED, messagesDelivered.getPeak(), messagesDelivered.getTotal())); + CurrentActor.get().message(VirtualHostMessages.STATS_DATA(name, RECEIVED, dataReceived.getPeak() / 1024.0, dataReceived.getTotal())); + CurrentActor.get().message(VirtualHostMessages.STATS_MSGS(name, RECEIVED, messagesReceived.getPeak(), messagesReceived.getTotal())); + } } - } - if (_reset) + if (_reset) + { + resetStatistics(); + } + } + catch(Exception e) { - resetStatistics(); + ApplicationRegistry._logger.warn("Unexpected exception occured while reporting the statistics", e); + } + finally + { + CurrentActor.remove(); } - - CurrentActor.remove(); - } - } - - /** - * Get the ApplicationRegistry - * @return the IApplicationRegistry instance - * @throws IllegalStateException if no registry instance has been initialised. - */ - public static IApplicationRegistry getInstance() throws IllegalStateException - { - IApplicationRegistry iApplicationRegistry = _instance.get(); - if (iApplicationRegistry == null) - { - throw new IllegalStateException("No ApplicationRegistry has been initialised"); - } - else - { - return iApplicationRegistry; } } @@ -488,7 +238,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry } //Set the Actor for Broker Shutdown - CurrentActor.set(new BrokerActor(getRootMessageLogger())); + CurrentActor.set(new BrokerActor(_rootMessageLogger)); try { //Stop Statistics Reporting @@ -497,154 +247,34 @@ public abstract class ApplicationRegistry implements IApplicationRegistry _reportingTimer.cancel(); } - //Stop incoming connections - unbind(); + if (_broker != null) + { + _broker.setDesiredState(_broker.getActualState(), State.STOPPED); + } //Shutdown virtualhosts close(_virtualHostRegistry); - close(_authenticationManagerRegistry); - - close(_qmfService); - - close(_pluginManager); - - BrokerConfig broker = getBrokerConfig(); - if(broker != null) + if (_taskExecutor != null) { - broker.getSystem().removeBroker(broker); + _taskExecutor.stop(); } CurrentActor.get().message(BrokerMessages.STOPPED()); - } - finally - { - CurrentActor.remove(); - } - } - - private void unbind() - { - List removedAcceptors = new ArrayList(); - synchronized (_acceptors) - { - for (InetSocketAddress bindAddress : _acceptors.keySet()) - { - QpidAcceptor acceptor = _acceptors.get(bindAddress); - removedAcceptors.add(acceptor); - try - { - acceptor.getNetworkTransport().close(); - } - catch (Throwable e) - { - _logger.error("Unable to close network driver due to:" + e.getMessage()); - } + _logRecorder.closeLogRecorder(); - CurrentActor.get().message(BrokerMessages.SHUTTING_DOWN(acceptor.toString(), bindAddress.getPort())); - } } - synchronized (_portBindingListeners) - { - for(QpidAcceptor acceptor : removedAcceptors) - { - for(PortBindingListener listener : _portBindingListeners) - { - listener.unbound(acceptor); - } - } - } - } - - public ServerConfiguration getConfiguration() - { - return _configuration; - } - - public void addAcceptor(InetSocketAddress bindAddress, QpidAcceptor acceptor) - { - synchronized (_acceptors) - { - _acceptors.put(bindAddress, acceptor); - } - synchronized (_portBindingListeners) + finally { - for(PortBindingListener listener : _portBindingListeners) + if (_taskExecutor != null) { - listener.bound(acceptor, bindAddress); + _taskExecutor.stopImmediately(); } + CurrentActor.remove(); } - } - - public VirtualHostRegistry getVirtualHostRegistry() - { - return _virtualHostRegistry; - } - - public SecurityManager getSecurityManager() - { - return _securityManager; - } - - @Override - public AuthenticationManager getAuthenticationManager(SocketAddress address) - { - return _authenticationManagerRegistry.getAuthenticationManager(address); - } - - @Override - public IAuthenticationManagerRegistry getAuthenticationManagerRegistry() - { - return _authenticationManagerRegistry; - } - - public PluginManager getPluginManager() - { - return _pluginManager; - } - - public ConfigurationManager getConfigurationManager() - { - return _configurationManager; - } - - public RootMessageLogger getRootMessageLogger() - { - return _rootMessageLogger; - } - - public RootMessageLogger getCompositeStartupMessageLogger() - { - return _startupMessageLogger; - } - - public UUID getBrokerId() - { - return _brokerId; - } - - public QMFService getQMFService() - { - return _qmfService; - } - - public BrokerConfig getBrokerConfig() - { - return _brokerConfig; - } - - public void setBrokerConfig(final BrokerConfig broker) - { - _brokerConfig = broker; - } - - public VirtualHost createVirtualHost(final VirtualHostConfiguration vhostConfig) throws Exception - { - VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig); - _virtualHostRegistry.registerVirtualHost(virtualHost); - getBrokerConfig().addVirtualHost(virtualHost); - return virtualHost; + _store = null; + _broker = null; } public void registerMessageDelivered(long messageSize) @@ -713,60 +343,10 @@ public abstract class ApplicationRegistry implements IApplicationRegistry logActor.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory())); } + @Override public Broker getBroker() { return _broker; } - @Override - public void addPortBindingListener(PortBindingListener listener) - { - synchronized (_portBindingListeners) - { - _portBindingListeners.add(listener); - } - } - - - @Override - public boolean useHTTPManagement() - { - return _httpManagementPort != -1; - } - - @Override - public int getHTTPManagementPort() - { - return _httpManagementPort; - } - - @Override - public boolean useHTTPSManagement() - { - return _httpsManagementPort != -1; - } - - @Override - public int getHTTPSManagementPort() - { - return _httpsManagementPort; - } - - public LogRecorder getLogRecorder() - { - return _logRecorder; - } - - @Override - public void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener) - { - if(_authenticationManagerRegistry == null) - { - _authManagerChangeListeners.add(registryChangeListener); - } - else - { - _authenticationManagerRegistry.addRegistryChangeListener(registryChangeListener); - } - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java deleted file mode 100644 index 950a090b43..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java +++ /dev/null @@ -1,195 +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.registry; - -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.common.ServerPropertyNames; -import org.apache.qpid.server.configuration.BrokerConfig; -import org.apache.qpid.server.configuration.BrokerConfigType; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.SystemConfig; -import org.apache.qpid.server.configuration.VirtualHostConfig; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public class BrokerConfigAdapter implements BrokerConfig -{ - private final IApplicationRegistry _instance; - private SystemConfig _system; - - private final Map _vhosts = new ConcurrentHashMap(); - private final long _createTime = System.currentTimeMillis(); - private UUID _qmfId; - private String _federationTag; - - public BrokerConfigAdapter(final IApplicationRegistry instance) - { - _instance = instance; - _qmfId = instance.getConfigStore().createId(); - _federationTag = UUID.randomUUID().toString(); - } - - public void setSystem(final SystemConfig system) - { - _system = system; - } - - public SystemConfig getSystem() - { - return _system; - } - - public Integer getPort() - { - List ports = _instance.getConfiguration().getPorts(); - if(ports.size() > 0) - { - return Integer.valueOf(ports.get(0).toString()); - } - else - { - return 0; - } - } - - public Integer getWorkerThreads() - { - return _instance.getConfiguration().getConnectorProcessors(); - } - - public Integer getMaxConnections() - { - return 0; - } - - public Integer getConnectionBacklogLimit() - { - return 0; - } - - public Long getStagingThreshold() - { - return 0L; - } - - public Integer getManagementPublishInterval() - { - return 10000; - } - - public String getVersion() - { - return QpidProperties.getReleaseVersion() + " [Build: " + QpidProperties.getBuildVersion() + "]"; - } - - public String getDataDirectory() - { - return _instance.getConfiguration().getQpidWork(); - } - - public void addVirtualHost(final VirtualHostConfig virtualHost) - { - _vhosts.put(virtualHost.getQMFId(), virtualHost); - getConfigStore().addConfiguredObject(virtualHost); - - } - - private ConfigStore getConfigStore() - { - return _instance.getConfigStore(); - } - - public long getCreateTime() - { - return _createTime; - } - - public void createBrokerConnection(final String transport, - final String host, - final int port, - final boolean durable, - final String authMechanism, - final String username, - final String password) - { - VirtualHost vhost = _instance.getVirtualHostRegistry().getDefaultVirtualHost(); - vhost.createBrokerConnection(transport, host, port, "", durable, authMechanism, username, password); - } - - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public BrokerConfigType getConfigType() - { - return BrokerConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return _system; - } - - public boolean isDurable() - { - return false; - } - - public String getFederationTag() - { - return _federationTag; - } - - /** - * @see org.apache.qpid.server.configuration.BrokerConfig#getFeatures() - */ - public List getFeatures() - { - final List features = new ArrayList(); - if (!_instance.getConfiguration().getDisabledFeatures().contains(ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR)) - { - features.add(ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR); - } - - return Collections.unmodifiableList(features); - } - - @Override - public String toString() - { - return "BrokerConfigAdapter{" + - "_id=" + _qmfId + - ", _system=" + _system + - ", _vhosts=" + _vhosts + - ", _createTime=" + _createTime + - ", _federationTag='" + _federationTag + '\'' + - '}'; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java deleted file mode 100644 index 774d0338ef..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java +++ /dev/null @@ -1,42 +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.registry; - -import org.apache.commons.configuration.ConfigurationException; -import org.osgi.framework.BundleContext; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.configuration.ServerConfiguration; - -import java.io.File; - -public class ConfigurationFileApplicationRegistry extends ApplicationRegistry -{ - public ConfigurationFileApplicationRegistry(File configurationURL) throws ConfigurationException - { - this(configurationURL, null); - } - - public ConfigurationFileApplicationRegistry(File configurationURL, BundleContext bundleContext) throws ConfigurationException - { - super(new ServerConfiguration(configurationURL), bundleContext); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java index 88c3c93156..d12258d194 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java @@ -20,27 +20,8 @@ */ package org.apache.qpid.server.registry; -import org.apache.qpid.qmf.QMFService; -import org.apache.qpid.server.configuration.BrokerConfig; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfigurationManager; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.plugins.PluginManager; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry; import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.transport.QpidAcceptor; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.Map; -import java.util.UUID; public interface IApplicationRegistry extends StatisticsGatherer { @@ -56,80 +37,5 @@ public interface IApplicationRegistry extends StatisticsGatherer */ void close(); - /** - * Get the low level configuration. For use cases where the configured object approach is not required - * you can get the complete configuration information. - * @return a Commons Configuration instance - */ - ServerConfiguration getConfiguration(); - - /** - * Get the AuthenticationManager for the given socket address - * - * If no AuthenticationManager has been specifically set for the given address, then use the default - * AuthenticationManager - * - * @param address The (listening) socket address for which the AuthenticationManager is required - * @return the AuthenticationManager - */ - AuthenticationManager getAuthenticationManager(SocketAddress address); - - IAuthenticationManagerRegistry getAuthenticationManagerRegistry(); - - VirtualHostRegistry getVirtualHostRegistry(); - - SecurityManager getSecurityManager(); - - PluginManager getPluginManager(); - - ConfigurationManager getConfigurationManager(); - - RootMessageLogger getRootMessageLogger(); - - /** - * Register any acceptors for this registry - * @param bindAddress The address that the acceptor has been bound with - * @param acceptor The acceptor in use - */ - void addAcceptor(InetSocketAddress bindAddress, QpidAcceptor acceptor); - - public UUID getBrokerId(); - - QMFService getQMFService(); - - void setBrokerConfig(BrokerConfig broker); - - BrokerConfig getBrokerConfig(); - Broker getBroker(); - - VirtualHost createVirtualHost(VirtualHostConfiguration vhostConfig) throws Exception; - - ConfigStore getConfigStore(); - - void setConfigStore(ConfigStore store); - - void initialiseStatisticsReporting(); - - Map getAcceptors(); - - void addPortBindingListener(PortBindingListener listener); - - boolean useHTTPManagement(); - - int getHTTPManagementPort(); - - boolean useHTTPSManagement(); - - int getHTTPSManagementPort(); - - void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener); - - public interface PortBindingListener - { - public void bound(QpidAcceptor acceptor, InetSocketAddress bindAddress); - public void unbound(QpidAcceptor acceptor); - - } - } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/AbstractPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/AbstractPlugin.java deleted file mode 100644 index 704e50da5c..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/AbstractPlugin.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.security; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; - -/** - * This is intended as the parent for all simple plugins. - */ -public abstract class AbstractPlugin implements SecurityPlugin -{ - private final Logger _logger = Logger.getLogger(getClass()); - - private ConfigurationPlugin _config; - - public Result getDefault() - { - return Result.ABSTAIN; - } - - public abstract Result access(ObjectType object, Object instance); - - public abstract Result authorise(Operation operation, ObjectType object, ObjectProperties properties); - - public void configure(ConfigurationPlugin config) - { - _config = config; - } - - public ConfigurationPlugin getConfig() - { - return _config; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java deleted file mode 100644 index 236931e8cd..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/AbstractProxyPlugin.java +++ /dev/null @@ -1,122 +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; - -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; - -/** - * This {@link SecurityPlugin} proxies the authorise calls to a serries of methods, one per {@link Operation}. - * - */ -public abstract class AbstractProxyPlugin extends AbstractPlugin -{ - public Result authoriseConsume(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - - public Result authorisePublish(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - - public Result authoriseCreate(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - - public Result authoriseAccess(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - - public Result authoriseBind(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - - public Result authoriseUnbind(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - - public Result authoriseDelete(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - - public Result authorisePurge(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - - public Result authoriseUpdate(ObjectType object, ObjectProperties properties) - { - return getDefault(); - } - - public Result accessVirtualhost(Object instance) - { - return getDefault(); - } - - @Override - public Result access(ObjectType objectType, Object instance) - { - switch (objectType) - { - case VIRTUALHOST: - return accessVirtualhost(instance); - } - - return getDefault(); - } - - @Override - public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) - { - switch (operation) - { - case CONSUME: - return authoriseConsume(objectType, properties); - case PUBLISH: - return authorisePublish(objectType, properties); - case CREATE: - return authoriseCreate(objectType, properties); - case ACCESS: - return authoriseAccess(objectType, properties); - case BIND: - return authoriseBind(objectType, properties); - case UNBIND: - return authoriseUnbind(objectType, properties); - case DELETE: - return authoriseDelete(objectType, properties); - case PURGE: - return authorisePurge(objectType, properties); - case UPDATE: - return authoriseUpdate(objectType, properties); - } - - return getDefault(); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java b/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java new file mode 100644 index 0000000000..b4831f83e5 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/AccessControl.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security; + +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; + +/** + * The two methods, {@link #access(ObjectType, Object)} and {@link #authorise(Operation, ObjectType, ObjectProperties)}, + * return the {@link Result} of the security decision, which may be to {@link Result#ABSTAIN} if no decision is made. + */ +public interface AccessControl +{ + /** + * Default result for {@link #access(ObjectType, Object)} or {@link #authorise(Operation, ObjectType, ObjectProperties)}. + */ + Result getDefault(); + + /** + * Authorise access granted to an object instance. + */ + Result access(ObjectType objectType, Object instance); + + /** + * Authorise an operation on an object defined by a set of properties. + */ + Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java b/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java index 8f3bdf7738..8243fc3f75 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java @@ -24,14 +24,14 @@ import javax.security.auth.Subject; import java.security.Principal; /** - * Represents the authorization of the logged on user. - * + * Represents the authorization of the logged on user. + * */ public interface AuthorizationHolder { - /** + /** * Returns the {@link Subject} of the authorized user. This is guaranteed to - * contain at least one {@link org.apache.qpid.server.security.auth.sasl.UsernamePrincipal}, representing the the identity + * contain at least one {@link org.apache.qpid.server.security.auth.UsernamePrincipal}, representing the the identity * used when the user logged on to the application, and zero or more {@link org.apache.qpid.server.security.auth.sasl.GroupPrincipal} * representing the group(s) to which the user belongs. * @@ -39,10 +39,10 @@ public interface AuthorizationHolder */ Subject getAuthorizedSubject(); - /** + /** * Returns the {@link Principal} representing the the identity * used when the user logged on to the application. - * + * * @return a Principal */ Principal getAuthorizedPrincipal(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java index 436660cfaf..1a1cce171b 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java @@ -18,22 +18,23 @@ */ package org.apache.qpid.server.security; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.plugins.PluginManager; + +import org.apache.qpid.server.plugin.AccessControlFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; import org.apache.qpid.server.security.access.Operation; import static org.apache.qpid.server.security.access.ObjectType.EXCHANGE; +import static org.apache.qpid.server.security.access.ObjectType.GROUP; import static org.apache.qpid.server.security.access.ObjectType.METHOD; import static org.apache.qpid.server.security.access.ObjectType.QUEUE; +import static org.apache.qpid.server.security.access.ObjectType.USER; import static org.apache.qpid.server.security.access.ObjectType.VIRTUALHOST; import static org.apache.qpid.server.security.access.Operation.BIND; import static org.apache.qpid.server.security.access.Operation.CONSUME; @@ -45,103 +46,105 @@ import static org.apache.qpid.server.security.access.Operation.UNBIND; import javax.security.auth.Subject; import java.net.SocketAddress; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; /** - * The security manager contains references to all loaded {@link SecurityPlugin}s and delegates security decisions to them based + * The security manager contains references to all loaded {@link AccessControl}s and delegates security decisions to them based * on virtual host name. The plugins can be external OSGi .jar files that export the required classes or just internal * objects for simpler plugins. - * - * @see SecurityPlugin + * + * @see AccessControl */ public class SecurityManager { private static final Logger _logger = Logger.getLogger(SecurityManager.class); - + /** Container for the {@link java.security.Principal} that is using to this thread. */ private static final ThreadLocal _subject = new ThreadLocal(); - private static final ThreadLocal _accessChecksDisabled = new ThreadLocal() + + public static final ThreadLocal _accessChecksDisabled = new ClearingThreadLocal(false); + + private Map _globalPlugins = new HashMap(); + private Map _hostPlugins = new HashMap(); + + /** + * A special ThreadLocal, which calls remove() on itself whenever the value is + * the default, to avoid leaving a default value set after its use has passed. + */ + private static final class ClearingThreadLocal extends ThreadLocal { - protected Boolean initialValue() + private Boolean _defaultValue; + + public ClearingThreadLocal(Boolean defaultValue) { - return false; + super(); + _defaultValue = defaultValue; } - }; - private PluginManager _pluginManager; - private Map _pluginFactories = new HashMap(); - private Map _globalPlugins = new HashMap(); - private Map _hostPlugins = new HashMap(); + @Override + protected Boolean initialValue() + { + return _defaultValue; + } - public static class SecurityConfiguration extends ConfigurationPlugin - { - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() + @Override + public void set(Boolean value) { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException + if (value == _defaultValue) { - ConfigurationPlugin instance = new SecurityConfiguration(); - instance.setConfiguration(path, config); - return instance; + super.remove(); } - - public List getParentPaths() + else { - return Arrays.asList("security", "virtualhosts.virtualhost.security"); + super.set(value); } - }; - - @Override - public String[] getElementsProcessed() - { - return new String[]{"security"}; } - public void validateConfiguration() throws ConfigurationException + @Override + public Boolean get() { - if (getConfig().isEmpty()) + Boolean value = super.get(); + if (value == _defaultValue) { - throw new ConfigurationException("security section is incomplete, no elements found."); + super.remove(); } + return value; } } - - public SecurityManager(SecurityManager parent) throws ConfigurationException + /* + * Used by the VirtualHost to allow deferring to the broker level security plugins if required. + */ + public SecurityManager(SecurityManager parent, String aclFile) { - _pluginManager = parent._pluginManager; - _pluginFactories = parent._pluginFactories; - + this(aclFile); + // our global plugins are the parent's host plugins _globalPlugins = parent._hostPlugins; } - public SecurityManager(ConfigurationPlugin configuration, PluginManager manager) throws ConfigurationException + public SecurityManager(String aclFile) { - this(configuration, manager, null); - } - - public SecurityManager(ConfigurationPlugin configuration, PluginManager manager, SecurityPluginFactory plugin) throws ConfigurationException - { - _pluginManager = manager; - if (manager == null) // No plugin manager, no plugins + Map attributes = new HashMap(); + attributes.put("aclFile", aclFile); + for (AccessControlFactory provider : (new QpidServiceLoader()).instancesOf(AccessControlFactory.class)) { - return; + AccessControl accessControl = provider.createInstance(attributes); + if(accessControl != null) + { + addHostPlugin(accessControl); + } } - _pluginFactories = _pluginManager.getSecurityPlugins(); - if (plugin != null) + if(_logger.isDebugEnabled()) { - _pluginFactories.put(plugin.getPluginName(), plugin); + _logger.debug("Configured " + _hostPlugins.size() + " access control plugins"); } - - configureHostPlugins(configuration); } public static Subject getThreadSubject() @@ -154,41 +157,6 @@ public class SecurityManager _subject.set(subject); } - public void configureHostPlugins(ConfigurationPlugin hostConfig) throws ConfigurationException - { - _hostPlugins = configurePlugins(hostConfig); - } - - public void configureGlobalPlugins(ConfigurationPlugin configuration) throws ConfigurationException - { - _globalPlugins = configurePlugins(configuration); - } - - public Map configurePlugins(ConfigurationPlugin hostConfig) throws ConfigurationException - { - Map plugins = new HashMap(); - SecurityConfiguration securityConfig = hostConfig.getConfiguration(SecurityConfiguration.class.getName()); - - // If we have no security Configuration then there is nothing to configure. - if (securityConfig != null) - { - for (SecurityPluginFactory factory : _pluginFactories.values()) - { - SecurityPlugin plugin = factory.newInstance(securityConfig); - if (plugin != null) - { - plugins.put(factory.getPluginName(), plugin); - } - } - } - return plugins; - } - - public void addHostPlugin(SecurityPlugin plugin) - { - _hostPlugins.put(plugin.getClass().getName(), plugin); - } - public static Logger getLogger() { return _logger; @@ -205,7 +173,7 @@ public class SecurityManager private abstract class AccessCheck { - abstract Result allowed(SecurityPlugin plugin); + abstract Result allowed(AccessControl plugin); } private boolean checkAllPlugins(AccessCheck checker) @@ -215,16 +183,16 @@ public class SecurityManager return true; } - Map remainingPlugins = _globalPlugins.isEmpty() - ? Collections.emptyMap() - : _hostPlugins.isEmpty() ? _globalPlugins : new HashMap(_globalPlugins); - - if(!_hostPlugins.isEmpty()) + Map remainingPlugins = _globalPlugins.isEmpty() + ? Collections.emptyMap() + : _hostPlugins.isEmpty() ? _globalPlugins : new HashMap(_globalPlugins); + + if(!_hostPlugins.isEmpty()) { - for (Entry hostEntry : _hostPlugins.entrySet()) + for (Entry hostEntry : _hostPlugins.entrySet()) { // Create set of global only plugins - SecurityPlugin globalPlugin = remainingPlugins.get(hostEntry.getKey()); + AccessControl globalPlugin = remainingPlugins.get(hostEntry.getKey()); if (globalPlugin != null) { remainingPlugins.remove(hostEntry.getKey()); @@ -272,7 +240,7 @@ public class SecurityManager } } - for (SecurityPlugin plugin : remainingPlugins.values()) + for (AccessControl plugin : remainingPlugins.values()) { Result remaining = checker.allowed(plugin); if (remaining == Result.DEFER) @@ -284,16 +252,16 @@ public class SecurityManager return false; } } - + // getting here means either allowed or abstained from all plugins return true; } - + public boolean authoriseBind(final Exchange exch, final AMQQueue queue, final AMQShortString routingKey) { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.authorise(BIND, EXCHANGE, new ObjectProperties(exch, queue, routingKey)); } @@ -304,7 +272,7 @@ public class SecurityManager { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { ObjectProperties properties = new ObjectProperties(); properties.setName(methodName); @@ -318,11 +286,22 @@ public class SecurityManager }); } + public boolean accessManagement() + { + return checkAllPlugins(new AccessCheck() + { + Result allowed(AccessControl plugin) + { + return plugin.access(ObjectType.MANAGEMENT, null); + } + }); + } + public boolean accessVirtualhost(final String vhostname, final SocketAddress remoteAddress) { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.access(VIRTUALHOST, remoteAddress); } @@ -333,7 +312,7 @@ public class SecurityManager { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.authorise(CONSUME, QUEUE, new ObjectProperties(queue)); } @@ -345,7 +324,7 @@ public class SecurityManager { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.authorise(CREATE, EXCHANGE, new ObjectProperties(autoDelete, durable, exchangeName, internal, nowait, passive, exchangeType)); @@ -358,7 +337,7 @@ public class SecurityManager { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.authorise(CREATE, QUEUE, new ObjectProperties(autoDelete, durable, exclusive, nowait, passive, queueName, owner)); } @@ -369,7 +348,7 @@ public class SecurityManager { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.authorise(DELETE, QUEUE, new ObjectProperties(queue)); } @@ -380,13 +359,34 @@ public class SecurityManager { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.authorise(DELETE, EXCHANGE, new ObjectProperties(exchange.getName())); } }); } + public boolean authoriseGroupOperation(final Operation operation, final String groupName) + { + return checkAllPlugins(new AccessCheck() + { + Result allowed(AccessControl plugin) + { + return plugin.authorise(operation, GROUP, new ObjectProperties(groupName)); + } + }); + } + + public boolean authoriseUserOperation(final Operation operation, final String userName) + { + return checkAllPlugins(new AccessCheck() + { + Result allowed(AccessControl plugin) + { + return plugin.authorise(operation, USER, new ObjectProperties(userName)); + } + }); + } private ConcurrentHashMap> _immediatePublishPropsCache = new ConcurrentHashMap>(); @@ -428,7 +428,7 @@ public class SecurityManager { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.authorise(PURGE, QUEUE, new ObjectProperties(queue)); } @@ -439,7 +439,7 @@ public class SecurityManager { return checkAllPlugins(new AccessCheck() { - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.authorise(UNBIND, EXCHANGE, new ObjectProperties(exch, queue, routingKey)); } @@ -465,9 +465,16 @@ public class SecurityManager _props = props; } - Result allowed(SecurityPlugin plugin) + Result allowed(AccessControl plugin) { return plugin.authorise(PUBLISH, EXCHANGE, _props); } } + + + public void addHostPlugin(AccessControl plugin) + { + _hostPlugins.put(plugin.getClass().getName(), plugin); + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPlugin.java deleted file mode 100644 index c3c06bf206..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPlugin.java +++ /dev/null @@ -1,47 +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; - -import org.apache.qpid.server.plugins.Plugin; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; - -/** - * The two methods, {@link #access(ObjectType, Object)} and {@link #authorise(Operation, ObjectType, ObjectProperties)}, - * return the {@link Result} of the security decision, which may be to {@link Result#ABSTAIN} if no decision is made - * by this plugin. - */ -public interface SecurityPlugin extends Plugin -{ - /** - * Default result for {@link #access(ObjectType, Object)} or {@link #authorise(Operation, ObjectType, ObjectProperties)}. - */ - Result getDefault(); - - /** - * Authorise access granted to an object instance. - */ - Result access(ObjectType objectType, Object instance); - - /** - * Authorise an operation on an object defined by a set of properties. - */ - Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties); -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginActivator.java b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginActivator.java deleted file mode 100644 index 21c2d1cda5..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginActivator.java +++ /dev/null @@ -1,75 +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; - -import org.apache.log4j.Logger; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; - -/** - * An OSGi {@link BundleActivator} that loads a {@link SecurityPluginFactory}. - */ -public abstract class SecurityPluginActivator implements BundleActivator -{ - private static final Logger _logger = Logger.getLogger(SecurityPluginActivator.class); - - private SecurityPluginFactory _factory; - private ConfigurationPluginFactory _config; - private BundleContext _ctx; - private String _bundleName; - - /** Implement this to return the factory this plugin activates. */ - public abstract SecurityPluginFactory getFactory(); - - /** Implement this to return the factory this plugin activates. */ - public abstract ConfigurationPluginFactory getConfigurationFactory(); - - /** - * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) - */ - public void start(BundleContext ctx) throws Exception - { - _ctx = ctx; - _factory = getFactory(); - _config = getConfigurationFactory(); - _bundleName = ctx.getBundle().getSymbolicName(); - - // register the service - _logger.info("Registering security plugin: " + _bundleName); - _ctx.registerService(SecurityPluginFactory.class.getName(), _factory, null); - _ctx.registerService(ConfigurationPluginFactory.class.getName(), _config, null); - } - - /** - * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) - */ - public void stop(BundleContext context) throws Exception - { - _logger.info("Stopping security plugin: " + _bundleName); - - // null object references - _factory = null; - _config = null; - _ctx = null; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginFactory.java deleted file mode 100644 index fe81cba282..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityPluginFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.security; - -import org.apache.qpid.server.plugins.PluginFactory; - -/** - * The factory that generates instances of security plugins. Usually implemented as a static member class in the plugin itself. - */ -public interface SecurityPluginFactory extends PluginFactory -{ -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java b/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java new file mode 100644 index 0000000000..8138745486 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/SubjectCreator.java @@ -0,0 +1,137 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security; + +import java.security.Principal; + +import javax.security.auth.Subject; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.group.GroupPrincipalAccessor; + +/** + * Creates a {@link Subject} formed by the {@link Principal}'s returned from: + *

    + *
  1. Authenticating using an {@link AuthenticationManager}
  2. + *
  3. A {@link GroupPrincipalAccessor}
  4. + *
+ * + *

+ * SubjectCreator is a facade to the {@link AuthenticationManager}, and is intended to be + * the single place that {@link Subject}'s are created in the broker. + *

+ */ +public class SubjectCreator +{ + private AuthenticationManager _authenticationManager; + private GroupPrincipalAccessor _groupAccessor; + + public SubjectCreator(AuthenticationManager authenticationManager, GroupPrincipalAccessor groupAccessor) + { + _authenticationManager = authenticationManager; + _groupAccessor = groupAccessor; + } + + /** + * Gets the known SASL mechanisms + * + * @return SASL mechanism names, space separated. + */ + public String getMechanisms() + { + return _authenticationManager.getMechanisms(); + } + + /** + * @see AuthenticationManager#createSaslServer(String, String, Principal) + */ + public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException + { + return _authenticationManager.createSaslServer(mechanism, localFQDN, externalPrincipal); + } + + /** + * Authenticates a user using SASL negotiation. + * + * @param server SASL server + * @param response SASL response to process + */ + public SubjectAuthenticationResult authenticate(SaslServer server, byte[] response) + { + AuthenticationResult authenticationResult = _authenticationManager.authenticate(server, response); + if(server.isComplete()) + { + String username = server.getAuthorizationID(); + + return createResultWithGroups(username, authenticationResult); + } + else + { + return new SubjectAuthenticationResult(authenticationResult); + } + } + + /** + * Authenticates a user using their username and password. + */ + public SubjectAuthenticationResult authenticate(String username, String password) + { + final AuthenticationResult authenticationResult = _authenticationManager.authenticate(username, password); + + return createResultWithGroups(username, authenticationResult); + } + + private SubjectAuthenticationResult createResultWithGroups(String username, final AuthenticationResult authenticationResult) + { + if(authenticationResult.getStatus() == AuthenticationStatus.SUCCESS) + { + final Subject authenticationSubject = new Subject(); + + authenticationSubject.getPrincipals().addAll(authenticationResult.getPrincipals()); + authenticationSubject.getPrincipals().addAll(_groupAccessor.getGroupPrincipals(username)); + + authenticationSubject.setReadOnly(); + + return new SubjectAuthenticationResult(authenticationResult, authenticationSubject); + } + else + { + return new SubjectAuthenticationResult(authenticationResult); + } + } + + public Subject createSubjectWithGroups(String username) + { + Subject authenticationSubject = new Subject(); + + authenticationSubject.getPrincipals().add(new AuthenticatedPrincipal(username)); + authenticationSubject.getPrincipals().addAll(_groupAccessor.getGroupPrincipals(username)); + authenticationSubject.setReadOnly(); + + return authenticationSubject; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java index a9ec4d1647..8e38681e68 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java @@ -18,33 +18,31 @@ */ package org.apache.qpid.server.security.access; -import org.apache.commons.lang.StringUtils; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.queue.AMQQueue; - import java.util.ArrayList; import java.util.EnumMap; +import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.AMQQueue; + /** * An set of properties for an access control v2 rule {@link ObjectType}. - * + * * The {@link #matches(ObjectProperties)} method is intended to be used when determining precedence of rules, and * {@link #equals(Object)} and {@link #hashCode()} are intended for use in maps. This is due to the wildcard matching * described above. */ public class ObjectProperties { - /** serialVersionUID */ - private static final long serialVersionUID = -1356019341374170495L; - public static final String STAR= "*"; public static final ObjectProperties EMPTY = new ObjectProperties(); - + public enum Property { ROUTING_KEY, @@ -65,81 +63,89 @@ public class ObjectProperties AUTO_DELETE, COMPONENT, PACKAGE, - CLASS; - - public static Property parse(String text) + CLASS, + FROM_NETWORK, + FROM_HOSTNAME; + + private static final Map _canonicalNameToPropertyMap = new HashMap(); + + static { for (Property property : values()) { - if (property.getName().equalsIgnoreCase(text)) - { - return property; - } + _canonicalNameToPropertyMap.put(getCanonicalName(property.name()), property); + } + } + + /** + * Properties are parsed using their canonical name (see {@link #getCanonicalName(String)}) + * so that, for the sake of user-friendliness, the ACL file parses is insensitive to + * case and underscores. + */ + public static Property parse(String text) + { + String propertyName = getCanonicalName(text); + Property property = _canonicalNameToPropertyMap.get(propertyName); + + if(property == null) + { + throw new IllegalArgumentException("Not a valid property: " + text + + " because " + propertyName + + " is not in " + _canonicalNameToPropertyMap.keySet()); + } + else + { + return property; } - throw new IllegalArgumentException("Not a valid property: " + text); } - - public String getName() + + private static String getCanonicalName(String name) { - return StringUtils.remove(name(), '_').toLowerCase(); + return StringUtils.remove(name, '_').toLowerCase(); } - - public static List getPropertyNames() - { - List properties = new ArrayList(); - for (Property property : values()) - { - properties.add(property.getName()); - } - return properties; - } } private final EnumMap _properties = new EnumMap(Property.class); - public static List getAllPropertyNames() + public static List getAllPropertyNames() { - List properties = new ArrayList(); - for (Property property : Property.values()) - { - properties.add(StringUtils.remove(property.name(), '_').toLowerCase()); - } - return properties; - } - + List properties = new ArrayList(); + for (Property property : Property.values()) + { + properties.add(StringUtils.remove(property.name(), '_').toLowerCase()); + } + return properties; + } + public ObjectProperties() { - super(); } - + + public ObjectProperties(Property property, String value) + { + _properties.put(property, value); + } + public ObjectProperties(ObjectProperties copy) { - super(); - _properties.putAll(copy._properties); } - + public ObjectProperties(String name) { - super(); - setName(name); } - + public ObjectProperties(AMQShortString name) { - super(); - setName(name); } - + public ObjectProperties(AMQQueue queue) { - super(); - setName(queue.getName()); - + put(Property.AUTO_DELETE, queue.isAutoDelete()); put(Property.TEMPORARY, queue.isAutoDelete()); put(Property.DURABLE, queue.isDurable()); @@ -157,45 +163,45 @@ public class ObjectProperties put(Property.OWNER, queue.getAuthorizationHolder().getAuthorizedPrincipal().getName()); } } - + public ObjectProperties(Exchange exch, AMQQueue queue, AMQShortString routingKey) { this(queue); - - setName(exch.getName()); - + + setName(exch.getName()); + put(Property.QUEUE_NAME, queue.getName()); put(Property.ROUTING_KEY, routingKey); } - + public ObjectProperties(Exchange exch, AMQShortString routingKey) { this(exch.getName(), routingKey.asString()); } - + public ObjectProperties(String exchangeName, String routingKey, Boolean immediate) { this(exchangeName, routingKey); - + put(Property.IMMEDIATE, immediate); } - + public ObjectProperties(String exchangeName, String routingKey) { super(); - + setName(exchangeName); - + put(Property.ROUTING_KEY, routingKey); } - + public ObjectProperties(Boolean autoDelete, Boolean durable, AMQShortString exchangeName, Boolean internal, Boolean nowait, Boolean passive, AMQShortString exchangeType) { super(); - + setName(exchangeName); - + put(Property.AUTO_DELETE, autoDelete); put(Property.TEMPORARY, autoDelete); put(Property.DURABLE, durable); @@ -204,14 +210,14 @@ public class ObjectProperties put(Property.PASSIVE, passive); put(Property.TYPE, exchangeType); } - + public ObjectProperties(Boolean autoDelete, Boolean durable, Boolean exclusive, Boolean nowait, Boolean passive, AMQShortString queueName, String owner) { super(); - + setName(queueName); - + put(Property.AUTO_DELETE, autoDelete); put(Property.TEMPORARY, autoDelete); put(Property.DURABLE, durable); @@ -220,7 +226,7 @@ public class ObjectProperties put(Property.PASSIVE, passive); put(Property.OWNER, owner); } - + public ObjectProperties(Boolean exclusive, Boolean noAck, Boolean noLocal, Boolean nowait, AMQQueue queue) { this(queue); @@ -230,17 +236,7 @@ public class ObjectProperties put(Property.EXCLUSIVE, exclusive); put(Property.NO_WAIT, nowait); } - - public List getPropertyNames() - { - List properties = new ArrayList(); - for (Property property : _properties.keySet()) - { - properties.add(property.getName()); - } - return properties; - } - + public Boolean isSet(Property key) { return _properties.containsKey(key) && Boolean.valueOf(_properties.get(key)); @@ -255,17 +251,17 @@ public class ObjectProperties { return _properties.get(Property.NAME); } - + public void setName(String name) { _properties.put(Property.NAME, name); } - + public void setName(AMQShortString name) { put(Property.NAME, name); } - + public String put(Property key, AMQShortString value) { return put(key, value == null ? "" : value.asString()); @@ -275,7 +271,7 @@ public class ObjectProperties { return _properties.put(key, value == null ? "" : value.trim()); } - + public void put(Property key, Boolean value) { if (value != null) @@ -283,66 +279,64 @@ public class ObjectProperties _properties.put(key, Boolean.toString(value)); } } - + public boolean matches(ObjectProperties properties) { if (properties._properties.keySet().isEmpty()) { return true; } - + if (!_properties.keySet().containsAll(properties._properties.keySet())) { return false; } - + for (Map.Entry entry : properties._properties.entrySet()) { Property key = entry.getKey(); String ruleValue = entry.getValue(); - + String thisValue = _properties.get(key); - if (!valueMatches(thisValue, ruleValue)) + if (!valueMatches(thisValue, ruleValue)) { return false; } } - + return true; } - + private boolean valueMatches(String thisValue, String ruleValue) { return (StringUtils.isEmpty(ruleValue) || StringUtils.equals(thisValue, ruleValue)) || ruleValue.equals(STAR) - || (ruleValue.endsWith(STAR) + || (ruleValue.endsWith(STAR) && thisValue != null && thisValue.length() >= ruleValue.length() - 1 && thisValue.startsWith(ruleValue.substring(0, ruleValue.length() - 1))); } @Override - public boolean equals(Object o) + public boolean equals(Object obj) { - if (this == o) + if (obj == null) { - return true; + return false; } - if (o == null || getClass() != o.getClass()) + if (obj == this) { - return false; + return true; } - - ObjectProperties that = (ObjectProperties) o; - - if (_properties != null ? !_properties.equals(that._properties) : that._properties != null) + if (obj.getClass() != getClass()) { return false; } - - return true; + ObjectProperties rhs = (ObjectProperties) obj; + return new EqualsBuilder() + .append(_properties, rhs._properties).isEquals(); } @Override diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java index 90ecd1dd17..8bc4b9d278 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java @@ -41,12 +41,15 @@ public enum ObjectType { ALL(Operation.ALL), VIRTUALHOST(Operation.ALL, ACCESS), + MANAGEMENT(Operation.ALL, ACCESS), QUEUE(Operation.ALL, CREATE, DELETE, PURGE, CONSUME), EXCHANGE(Operation.ALL, ACCESS, CREATE, DELETE, BIND, UNBIND, PUBLISH), LINK, // Not allowed in the Java broker ROUTE, // Not allowed in the Java broker - METHOD(Operation.ALL, ACCESS, UPDATE); - + METHOD(Operation.ALL, ACCESS, UPDATE), + USER(Operation.ALL, CREATE, DELETE, UPDATE), + GROUP(Operation.ALL, CREATE, DELETE, UPDATE); + private EnumSet _actions; private ObjectType() diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java deleted file mode 100644 index 4df135a4ca..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/BasicPlugin.java +++ /dev/null @@ -1,43 +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.access.plugins; - -import org.apache.qpid.server.security.AbstractPlugin; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; - -/** - * This {@link org.apache.qpid.server.security.SecurityPlugin} simply abstains from all authorisation requests and ignores configuration. - */ -public abstract class BasicPlugin extends AbstractPlugin -{ - public Result access(ObjectType objectType, Object instance) - { - return getDefault(); - } - - public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) - { - return getDefault(); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccess.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccess.java deleted file mode 100644 index 4b7a2fb457..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/plugins/LegacyAccess.java +++ /dev/null @@ -1,86 +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.access.plugins; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.security.SecurityPluginFactory; - -import java.util.Arrays; -import java.util.List; - -/** - * The LegacyAccess plugin is used internally and simply ignores legacy elements of the configuration file. - */ -public class LegacyAccess extends BasicPlugin -{ - public static class LegacyAccessConfiguration extends ConfigurationPlugin { - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public List getParentPaths() - { - return Arrays.asList("security.msg-auth", "virtualhosts.virtualhost.security.msg-auth"); - } - - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - ConfigurationPlugin instance = new LegacyAccessConfiguration(); - instance.setConfiguration(path, config); - return instance; - } - }; - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - } - - public static final SecurityPluginFactory FACTORY = new SecurityPluginFactory() - { - public LegacyAccess newInstance(ConfigurationPlugin config) throws ConfigurationException - { - LegacyAccessConfiguration configuration = config.getConfiguration(LegacyAccessConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - return null; - } - - LegacyAccess plugin = new LegacyAccess(); - plugin.configure(configuration); - return plugin; - } - - public String getPluginName() - { - return LegacyAccess.class.getName(); - } - - public Class getPluginClass() - { - return LegacyAccess.class; - } - }; - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipal.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipal.java new file mode 100644 index 0000000000..fb31132514 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipal.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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; + +import java.io.Serializable; +import java.security.Principal; +import java.util.Set; + +import javax.security.auth.Subject; + +import org.apache.qpid.server.security.auth.UsernamePrincipal; + +/** + * A simple Principal wrapper. Exists to allow us to identify the "primary" principal + * by calling {@link Subject#getPrincipals(Class)}, passing in {@link AuthenticatedPrincipal}.class, + * e.g. when logging. + */ +public final class AuthenticatedPrincipal implements Principal, Serializable +{ + private final Principal _wrappedPrincipal; + + /** convenience constructor for the common case where we're wrapping a {@link UsernamePrincipal} */ + public AuthenticatedPrincipal(String userPrincipalName) + { + this(new UsernamePrincipal(userPrincipalName)); + } + + public AuthenticatedPrincipal(Principal wrappedPrincipal) + { + if(wrappedPrincipal == null) + { + throw new IllegalArgumentException("Wrapped principal is null"); + } + + _wrappedPrincipal = wrappedPrincipal; + } + + @Override + public String getName() + { + return _wrappedPrincipal.getName(); + } + + @Override + public int hashCode() + { + return _wrappedPrincipal.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (!(obj instanceof AuthenticatedPrincipal)) + { + return false; + } + + AuthenticatedPrincipal other = (AuthenticatedPrincipal) obj; + + return _wrappedPrincipal.equals(other._wrappedPrincipal); + } + + public static AuthenticatedPrincipal getOptionalAuthenticatedPrincipalFromSubject(final Subject authSubject) + { + return getAuthenticatedPrincipalFromSubject(authSubject, true); + } + + public static AuthenticatedPrincipal getAuthenticatedPrincipalFromSubject(final Subject authSubject) + { + return getAuthenticatedPrincipalFromSubject(authSubject, false); + } + + private static AuthenticatedPrincipal getAuthenticatedPrincipalFromSubject(final Subject authSubject, boolean isPrincipalOptional) + { + if (authSubject == null) + { + throw new IllegalArgumentException("No authenticated subject."); + } + + final Set principals = authSubject.getPrincipals(AuthenticatedPrincipal.class); + int numberOfAuthenticatedPrincipals = principals.size(); + + if(numberOfAuthenticatedPrincipals == 0 && isPrincipalOptional) + { + return null; + } + else + { + if (numberOfAuthenticatedPrincipals != 1) + { + throw new IllegalArgumentException( + "Can't find single AuthenticatedPrincipal in authenticated subject. There were " + + numberOfAuthenticatedPrincipals + + " authenticated principals out of a total number of principals of: " + authSubject.getPrincipals()); + } + return principals.iterator().next(); + } + } + + @Override + public String toString() + { + return getName(); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java index 949c0f2b89..09bf6cf3b1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java @@ -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,15 +20,20 @@ */ package org.apache.qpid.server.security.auth; -import javax.security.auth.Subject; +import java.security.Principal; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; /** - * Encapsulates the result of an attempt to authenticate. + * Encapsulates the result of an attempt to authenticate using an {@link AuthenticationManager}. *

* The authentication status describes the overall outcome. *

*

    - *
  1. If authentication status is SUCCESS, the subject will be populated. + *
  2. If authentication status is SUCCESS, at least one {@link Principal} will be populated. *
  3. *
  4. If authentication status is CONTINUE, the authentication has failed because the user * supplied incorrect credentials (etc). If the authentication requires it, the next challenge @@ -40,6 +45,8 @@ import javax.security.auth.Subject; *
  5. *
* + * The main principal provided to the constructor is wrapped in an {@link AuthenticatedPrincipal} + * to make it easier for the rest of the application to identify it among the set of other principals. */ public class AuthenticationResult { @@ -56,37 +63,59 @@ public class AuthenticationResult private final AuthenticationStatus _status; private final byte[] _challenge; private final Exception _cause; - private final Subject _subject; + private final Set _principals = new HashSet(); + private final Principal _mainPrincipal; public AuthenticationResult(final AuthenticationStatus status) { this(null, status, null); } + public AuthenticationResult(Principal mainPrincipal) + { + this(mainPrincipal, Collections.emptySet()); + } + + public AuthenticationResult(Principal mainPrincipal, Set otherPrincipals) + { + AuthenticatedPrincipal specialQpidAuthenticatedPrincipal = new AuthenticatedPrincipal(mainPrincipal); + _principals.addAll(otherPrincipals); + _principals.remove(mainPrincipal); + _principals.add(specialQpidAuthenticatedPrincipal); + _mainPrincipal = mainPrincipal; + + _status = AuthenticationStatus.SUCCESS; + _challenge = null; + _cause = null; + } + public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status) { - this(challenge, status, null); + _challenge = challenge; + _status = status; + _cause = null; + _mainPrincipal = null; } public AuthenticationResult(final AuthenticationStatus error, final Exception cause) { - this(null, error, cause); + _status = error; + _challenge = null; + _cause = cause; + _mainPrincipal = null; } public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status, final Exception cause) { - this._status = status; - this._challenge = challenge; - this._cause = cause; - this._subject = null; - } + if(status == AuthenticationStatus.SUCCESS) + { + throw new IllegalArgumentException("Successful authentication requires at least one principal"); + } - public AuthenticationResult(final Subject subject) - { - this._status = AuthenticationStatus.SUCCESS; - this._challenge = null; - this._cause = null; - this._subject = subject; + _status = status; + _challenge = challenge; + _cause = cause; + _mainPrincipal = null; } public Exception getCause() @@ -104,9 +133,13 @@ public class AuthenticationResult return _challenge; } - public Subject getSubject() + public Set getPrincipals() { - return _subject; + return _principals; } + public Principal getMainPrincipal() + { + return _mainPrincipal; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/SubjectAuthenticationResult.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/SubjectAuthenticationResult.java new file mode 100644 index 0000000000..3be96b87eb --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/SubjectAuthenticationResult.java @@ -0,0 +1,76 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth; + +import java.security.Principal; + +import javax.security.auth.Subject; + +import org.apache.qpid.server.security.SubjectCreator; + +/** + * Encapsulates the result of an attempt to authenticate using a {@link SubjectCreator}. + * + *

+ * iff authentication was successful, {@link #getSubject()} will return a non-null value and + * {@link #getStatus()} will return {@link AuthenticationResult.AuthenticationStatus#SUCCESS}. + * + * In this case, the {@link Subject} will contain the user {@link Principal} and zero or more other principals + * representing groups. + *

+ * @see SubjectCreator + */ +public class SubjectAuthenticationResult +{ + private final AuthenticationResult _authenticationResult; + private final Subject _subject; + + public SubjectAuthenticationResult(AuthenticationResult authenticationResult, Subject subject) + { + _authenticationResult = authenticationResult; + _subject = subject; + } + + public SubjectAuthenticationResult(AuthenticationResult unsuccessfulAuthenticationResult) + { + this(unsuccessfulAuthenticationResult, null); + } + + public Exception getCause() + { + return _authenticationResult.getCause(); + } + + public AuthenticationResult.AuthenticationStatus getStatus() + { + return _authenticationResult.getStatus(); + } + + public byte[] getChallenge() + { + return _authenticationResult.getChallenge(); + } + + public Subject getSubject() + { + return _subject; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/UsernamePrincipal.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/UsernamePrincipal.java new file mode 100644 index 0000000000..5b3c1d59cf --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/UsernamePrincipal.java @@ -0,0 +1,77 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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; + +import java.io.Serializable; +import java.security.Principal; + +/** A principal that is just a wrapper for a simple username. */ +public class UsernamePrincipal implements Principal, Serializable +{ + private final String _name; + + public UsernamePrincipal(String name) + { + if (name == null) + { + throw new IllegalArgumentException("name cannot be null"); + } + _name = name; + } + + public String getName() + { + return _name; + } + + public String toString() + { + return _name; + } + + @Override + public int hashCode() + { + final int prime = 31; + return prime * _name.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + else + { + if (obj instanceof UsernamePrincipal) + { + UsernamePrincipal other = (UsernamePrincipal) obj; + return _name.equals(other._name); + } + else + { + return false; + } + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java index cac60a5283..578bb96efa 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java @@ -21,9 +21,9 @@ package org.apache.qpid.server.security.auth.database; import org.apache.log4j.Logger; +import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser; import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.AccountNotFoundException; diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java index 67f4b7344a..605d2d019d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabase.java @@ -32,6 +32,8 @@ import java.util.Map; /** Represents a "user database" which is really a way of storing principals (i.e. usernames) and passwords. */ public interface PrincipalDatabase { + void setPasswordFile(String passwordFile) throws IOException; + /** * Set the password for a given principal in the specified callback. This is used for certain SASL providers. The * user database implementation should look up the password in any way it chooses and set it in the callback by diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java deleted file mode 100644 index 4203cb0e07..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java +++ /dev/null @@ -1,169 +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.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; - -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.login.AccountNotFoundException; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.Principal; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -public class PropertiesPrincipalDatabase implements PrincipalDatabase -{ - private Properties _users; - - private Map _saslServers; - - public PropertiesPrincipalDatabase(Properties users) - { - _users = users; - - _saslServers = new HashMap(); - - /** - * Create Authenticators for Properties Principal Database. - */ - - // 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 setPassword(Principal principal, PasswordCallback callback) throws IOException, AccountNotFoundException - { - if (principal == null) - { - throw new IllegalArgumentException("principal must not be null"); - } - - - - final String pwd = _users.getProperty(principal.getName()); - - if (pwd != null) - { - callback.setPassword(pwd.toCharArray()); - } - else - { - throw new AccountNotFoundException("No account found for principal " + principal); - } - } - - public boolean verifyPassword(String principal, char[] password) throws AccountNotFoundException - { - //fixme this is not correct as toCharArray is not safe based on the type of string. - char[] pwd = _users.getProperty(principal).toCharArray(); - - return compareCharArray(pwd, password); - } - - public boolean updatePassword(Principal principal, char[] password) throws AccountNotFoundException - { - return false; // updates denied - } - - public boolean createPrincipal(Principal principal, char[] 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 getMechanisms() - { - return _saslServers; - } - - public List getUsers() - { - return new LinkedList(); //todo - } - - public Principal getUser(String username) - { - if (_users.getProperty(username) != null) - { - return new UsernamePrincipal(username); - } - else - { - return null; - } - } - - public void reload() throws IOException - { - //No file to update from, so do nothing. - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractPrincipalDatabaseAuthManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractPrincipalDatabaseAuthManagerFactory.java new file mode 100644 index 0000000000..ff21d63c87 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractPrincipalDatabaseAuthManagerFactory.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.io.IOException; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.security.auth.database.PrincipalDatabase; + +/** + * Factory for {@link PrincipalDatabaseAuthenticationManager} objects configured + * with either the Plain or Base64MD5 digest {@link PrincipalDatabase} + * implementation. + */ +public abstract class AbstractPrincipalDatabaseAuthManagerFactory implements AuthenticationManagerFactory +{ + public static final String ATTRIBUTE_PATH = "path"; + + private static final Logger LOGGER = Logger.getLogger(AbstractPrincipalDatabaseAuthManagerFactory.class); + + @Override + public AuthenticationManager createInstance(Map attributes) + { + if (attributes == null || !getType().equals(attributes.get(ATTRIBUTE_TYPE))) + { + return null; + } + + String passwordFile = (String) attributes.get(ATTRIBUTE_PATH); + if (passwordFile == null) + { + LOGGER.warn("Password file path must not be null"); + return null; + } + + PrincipalDatabase principalDatabase = createPrincipalDatabase(); + try + { + principalDatabase.setPasswordFile(passwordFile); + } + catch (IOException e) + { + throw new RuntimeException(e.getMessage(), e); + } + + return new PrincipalDatabaseAuthenticationManager(principalDatabase); + } + + abstract String getType(); + + abstract PrincipalDatabase createPrincipalDatabase(); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java index 5676c43754..dd4c2e717a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java @@ -21,31 +21,25 @@ package org.apache.qpid.server.security.auth.manager; import java.security.Principal; -import java.util.Arrays; -import java.util.List; + import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; + import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.auth.sasl.anonymous.AnonymousInitialiser; import org.apache.qpid.server.security.auth.sasl.anonymous.AnonymousSaslServer; public class AnonymousAuthenticationManager implements AuthenticationManager { - private static final Logger _logger = Logger.getLogger(AnonymousAuthenticationManager.class); - private static final AnonymousInitialiser SASL_INITIALISER = new AnonymousInitialiser(); private static final String ANONYMOUS = SASL_INITIALISER.getMechanismName(); - private static final Principal ANONYMOUS_PRINCIPAL = new UsernamePrincipal("ANONYMOUS"); + public static final String ANONYMOUS_USERNAME = "ANONYMOUS"; + + public static final Principal ANONYMOUS_PRINCIPAL = new UsernamePrincipal(ANONYMOUS_USERNAME); public static final Subject ANONYMOUS_SUBJECT = new Subject(); static @@ -53,76 +47,11 @@ public class AnonymousAuthenticationManager implements AuthenticationManager ANONYMOUS_SUBJECT.getPrincipals().add(ANONYMOUS_PRINCIPAL); } - private static final AuthenticationResult ANONYMOUS_AUTHENTICATION = new AuthenticationResult(ANONYMOUS_SUBJECT); - - - private static CallbackHandler _callbackHandler = SASL_INITIALISER.getCallbackHandler(); + private static final AuthenticationResult ANONYMOUS_AUTHENTICATION = new AuthenticationResult(ANONYMOUS_PRINCIPAL); static final AnonymousAuthenticationManager INSTANCE = new AnonymousAuthenticationManager(); - public static class AnonymousAuthenticationManagerConfiguration extends ConfigurationPlugin - { - - public static final ConfigurationPluginFactory FACTORY = - new ConfigurationPluginFactory() - { - public List getParentPaths() - { - return Arrays.asList("security.anonymous-auth-manager"); - } - - public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException - { - final ConfigurationPlugin instance = new AnonymousAuthenticationManagerConfiguration(); - - instance.setConfiguration(path, config); - return instance; - } - }; - - public String[] getElementsProcessed() - { - return new String[0]; - } - - public void validateConfiguration() throws ConfigurationException - { - } - - } - - - public static final AuthenticationManagerPluginFactory FACTORY = new AuthenticationManagerPluginFactory() - { - public AnonymousAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException - { - AnonymousAuthenticationManagerConfiguration configuration = - config == null - ? null - : (AnonymousAuthenticationManagerConfiguration) config.getConfiguration(AnonymousAuthenticationManagerConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - _logger.info("No authentication-manager configuration found for AnonymousAuthenticationManager"); - return null; - } - return INSTANCE; - } - - public Class getPluginClass() - { - return AnonymousAuthenticationManager.class; - } - - public String getPluginName() - { - return AnonymousAuthenticationManager.class.getName(); - } - }; - - - private AnonymousAuthenticationManager() + AnonymousAuthenticationManager() { } @@ -184,9 +113,4 @@ public class AnonymousAuthenticationManager implements AuthenticationManager public void close() { } - - @Override - public void configure(ConfigurationPlugin config) throws ConfigurationException - { - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerFactory.java new file mode 100644 index 0000000000..1b1995500c --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.util.Map; + +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; + +public class AnonymousAuthenticationManagerFactory implements AuthenticationManagerFactory +{ + public static final String PROVIDER_TYPE = AnonymousAuthenticationManager.class.getSimpleName(); + + @Override + public AuthenticationManager createInstance(Map attributes) + { + if (attributes != null && PROVIDER_TYPE.equals(attributes.get(ATTRIBUTE_TYPE))) + { + return new AnonymousAuthenticationManager(); + } + return null; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java index ccddcb7669..c1a694f148 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java @@ -24,22 +24,22 @@ import java.security.Principal; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import org.apache.qpid.common.Closeable; -import org.apache.qpid.server.plugins.Plugin; import org.apache.qpid.server.security.auth.AuthenticationResult; /** * Implementations of the AuthenticationManager are responsible for determining * the authenticity of a user's credentials. - * - * If the authentication is successful, the manager is responsible for producing a populated - * {@link javax.security.auth.Subject} containing the user's identity and zero or more principals representing - * groups to which the user belongs. + *

+ * If the authentication is successful, the manager is responsible for producing an + * {@link AuthenticationResult} containing the user's main {@link Principal} and zero or + * more other implementation-specific principals. + *

*

* The {@link #initialise()} method is responsible for registering SASL mechanisms required by * the manager. The {@link #close()} method must reverse this registration. - * + *

*/ -public interface AuthenticationManager extends Closeable, Plugin +public interface AuthenticationManager extends Closeable { /** The name for the required SASL Server mechanisms */ public static final String PROVIDER_NAME= "AMQSASLProvider-Server"; @@ -88,5 +88,4 @@ public interface AuthenticationManager extends Closeable, Plugin * @return authentication result */ AuthenticationResult authenticate(String username, String password); - } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java deleted file mode 100644 index a51f195761..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java +++ /dev/null @@ -1,32 +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.manager; - -import org.apache.qpid.server.plugins.PluginFactory; - -/** - * Factory producing authentication producing configured, initialised authentication - * managers. - */ -public interface AuthenticationManagerPluginFactory extends PluginFactory -{ - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java deleted file mode 100644 index 89a4d8ae66..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java +++ /dev/null @@ -1,203 +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.manager; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.common.Closeable; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.plugins.Plugin; -import org.apache.qpid.server.plugins.PluginManager; -import org.apache.qpid.server.security.SecurityManager.SecurityConfiguration; - -/** - * A concrete implementation of {@link IAuthenticationManagerRegistry} that registers all {@link AuthenticationManager} - * instances defined in the configuration, building an optional mapping between port number and AuthenticationManager. - * - *

The default AuthenticationManager is either the one nominated as default within the configuration with - * {@link ServerConfiguration#getDefaultAuthenticationManager()}, or if there is only one, it is implicitly - * the default.

- * - *

It is important to {@link #close()} the registry after use and this allows the AuthenticationManagers - * to reverse any security registrations they have performed.

- */ -public class AuthenticationManagerRegistry implements Closeable, IAuthenticationManagerRegistry -{ - private final Map _classToAuthManagerMap = new HashMap(); - private final AuthenticationManager _defaultAuthenticationManager; - private final Map _portToAuthenticationManagerMap; - private final List _listeners = - Collections.synchronizedList(new ArrayList()); - - public AuthenticationManagerRegistry(ServerConfiguration serverConfiguration, PluginManager _pluginManager) - throws ConfigurationException - { - final Collection> factories = _pluginManager.getAuthenticationManagerPlugins().values(); - - if (factories.size() == 0) - { - throw new ConfigurationException("No authentication manager factory plugins found. Check the desired authentication" + - " manager plugin has been placed in the plugins directory."); - } - - final SecurityConfiguration securityConfiguration = serverConfiguration.getConfiguration(SecurityConfiguration.class.getName()); - - boolean willClose = true; - try - { - createAuthenticationManagersRejectingDuplicates(factories, securityConfiguration); - - if(_classToAuthManagerMap.isEmpty()) - { - throw new ConfigurationException("No authentication managers configured within the configuration file."); - } - - _defaultAuthenticationManager = getDefaultAuthenticationManager(serverConfiguration); - - _portToAuthenticationManagerMap = getPortToAuthenticationManagerMap(serverConfiguration); - willClose = false; - } - finally - { - // if anything went wrong whilst configuring the registry, try to close all the AuthentcationManagers instantiated so far. - // This is done to allow the AuthenticationManager to undo any security registrations that they have performed. - if (willClose) - { - close(); - } - } - } - - @Override - public AuthenticationManager getAuthenticationManager(SocketAddress address) - { - AuthenticationManager authManager = - address instanceof InetSocketAddress - ? _portToAuthenticationManagerMap.get(((InetSocketAddress)address).getPort()) - : null; - - return authManager == null ? _defaultAuthenticationManager : authManager; - } - - @Override - public void close() - { - for (AuthenticationManager authManager : _classToAuthManagerMap.values()) - { - authManager.close(); - } - } - - private void createAuthenticationManagersRejectingDuplicates( - final Collection> factories, - final SecurityConfiguration securityConfiguration) - throws ConfigurationException - { - for(AuthenticationManagerPluginFactory factory : factories) - { - final AuthenticationManager tmp = factory.newInstance(securityConfiguration); - if (tmp != null) - { - if(_classToAuthManagerMap.containsKey(tmp.getClass().getSimpleName())) - { - throw new ConfigurationException("Cannot configure more than one authentication manager of type " - + tmp.getClass().getSimpleName() + "." - + " Remove configuration for one of the authentication managers."); - } - _classToAuthManagerMap.put(tmp.getClass().getSimpleName(),tmp); - - for(RegistryChangeListener listener : _listeners) - { - listener.authenticationManagerRegistered(tmp); - } - } - } - } - - private AuthenticationManager getDefaultAuthenticationManager( - ServerConfiguration serverConfiguration) - throws ConfigurationException - { - final AuthenticationManager defaultAuthenticationManager; - if(_classToAuthManagerMap.size() == 1) - { - defaultAuthenticationManager = _classToAuthManagerMap.values().iterator().next(); - } - else if(serverConfiguration.getDefaultAuthenticationManager() != null) - { - defaultAuthenticationManager = _classToAuthManagerMap.get(serverConfiguration.getDefaultAuthenticationManager()); - if(defaultAuthenticationManager == null) - { - throw new ConfigurationException("No authentication managers configured of type " - + serverConfiguration.getDefaultAuthenticationManager() - + " which is specified as the default. Available managers are: " - + _classToAuthManagerMap.keySet()); - } - } - else - { - throw new ConfigurationException("If more than one authentication manager is configured a default MUST be specified."); - } - return defaultAuthenticationManager; - } - - private Map getPortToAuthenticationManagerMap( - ServerConfiguration serverConfiguration) - throws ConfigurationException - { - Map portToAuthenticationManagerMap = new HashMap(); - - for(Map.Entry portMapping : serverConfiguration.getPortAuthenticationMappings().entrySet()) - { - - AuthenticationManager authenticationManager = _classToAuthManagerMap.get(portMapping.getValue()); - if(authenticationManager == null) - { - throw new ConfigurationException("Unknown authentication manager class " + portMapping.getValue() + - " configured for port " + portMapping.getKey()); - } - portToAuthenticationManagerMap.put(portMapping.getKey(), authenticationManager); - } - - return portToAuthenticationManagerMap; - } - - @Override - public Map getAvailableAuthenticationManagers() - { - return Collections.unmodifiableMap(new HashMap(_classToAuthManagerMap)); - } - - @Override - public void addRegistryChangeListener(RegistryChangeListener listener) - { - _listeners.add(listener); - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/Base64MD5PasswordFileAuthenticationManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/Base64MD5PasswordFileAuthenticationManagerFactory.java new file mode 100644 index 0000000000..c61567ef77 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/Base64MD5PasswordFileAuthenticationManagerFactory.java @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase; +import org.apache.qpid.server.security.auth.database.PrincipalDatabase; + +public class Base64MD5PasswordFileAuthenticationManagerFactory extends AbstractPrincipalDatabaseAuthManagerFactory +{ + public static final String PROVIDER_TYPE = "Base64MD5PasswordFileAuthenticationProvider"; + + @Override + String getType() + { + return PROVIDER_TYPE; + } + + @Override + PrincipalDatabase createPrincipalDatabase() + { + return new Base64MD5PasswordFilePrincipalDatabase(); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java index 2d6866b657..9ed8cf7fed 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java @@ -19,90 +19,19 @@ package org.apache.qpid.server.security.auth.manager; import java.security.Principal; -import java.util.Arrays; -import java.util.List; -import javax.security.auth.Subject; + import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; + import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.auth.sasl.external.ExternalSaslServer; public class ExternalAuthenticationManager implements AuthenticationManager { - private static final Logger _logger = Logger.getLogger(ExternalAuthenticationManager.class); - private static final String EXTERNAL = "EXTERNAL"; - static final ExternalAuthenticationManager INSTANCE = new ExternalAuthenticationManager(); - - public static class ExternalAuthenticationManagerConfiguration extends ConfigurationPlugin - { - - public static final ConfigurationPluginFactory FACTORY = - new ConfigurationPluginFactory() - { - public List getParentPaths() - { - return Arrays.asList("security.external-auth-manager"); - } - - public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException - { - final ConfigurationPlugin instance = new ExternalAuthenticationManagerConfiguration(); - - instance.setConfiguration(path, config); - return instance; - } - }; - - public String[] getElementsProcessed() - { - return new String[0]; - } - - public void validateConfiguration() throws ConfigurationException - { - } - - } - - - public static final AuthenticationManagerPluginFactory FACTORY = new AuthenticationManagerPluginFactory() - { - public ExternalAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException - { - ExternalAuthenticationManagerConfiguration configuration = - config == null - ? null - : (ExternalAuthenticationManagerConfiguration) config.getConfiguration(ExternalAuthenticationManagerConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - _logger.info("No authentication-manager configuration found for ExternalAuthenticationManager"); - return null; - } - return INSTANCE; - } - - public Class getPluginClass() - { - return ExternalAuthenticationManager.class; - } - - public String getPluginName() - { - return ExternalAuthenticationManager.class.getName(); - } - }; - - - private ExternalAuthenticationManager() + ExternalAuthenticationManager() { } @@ -137,15 +66,13 @@ public class ExternalAuthenticationManager implements AuthenticationManager // Process response from the client try { - byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); + server.evaluateResponse(response != null ? response : new byte[0]); Principal principal = ((ExternalSaslServer)server).getAuthenticatedPrincipal(); if(principal != null) { - final Subject subject = new Subject(); - subject.getPrincipals().add(principal); - return new AuthenticationResult(subject); + return new AuthenticationResult(principal); } else { @@ -162,16 +89,11 @@ public class ExternalAuthenticationManager implements AuthenticationManager @Override public AuthenticationResult authenticate(String username, String password) { - return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + return new AuthenticationResult(new UsernamePrincipal(username)); } @Override public void close() { } - - @Override - public void configure(ConfigurationPlugin config) throws ConfigurationException - { - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java new file mode 100644 index 0000000000..3c3628e9db --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerFactory.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.util.Map; + +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; + +public class ExternalAuthenticationManagerFactory implements AuthenticationManagerFactory +{ + public static final String PROVIDER_TYPE = ExternalAuthenticationManager.class.getSimpleName(); + + @Override + public AuthenticationManager createInstance(Map attributes) + { + if (attributes != null && PROVIDER_TYPE.equals(attributes.get(ATTRIBUTE_TYPE))) + { + return new ExternalAuthenticationManager(); + } + return null; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java deleted file mode 100644 index 485ca2e1e9..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.security.auth.manager; - -import java.net.SocketAddress; - -import java.util.Map; -import org.apache.qpid.common.Closeable; -import org.apache.qpid.server.virtualhost.VirtualHost; - -/** - * Registry for {@link AuthenticationManager} instances. - * - *

A lookup method {@link #getAuthenticationManager(SocketAddress)} allows a caller to determine - * the AuthenticationManager associated with a particular port number.

- * - *

It is important to {@link #close()} the registry after use and this allows the AuthenticationManagers - * to reverse any security registrations they have performed.

- */ -public interface IAuthenticationManagerRegistry extends Closeable -{ - /** - * Returns the {@link AuthenticationManager} associated with a particular {@link SocketAddress}. - * If no authentication manager is associated with this address, a default authentication manager will be - * returned. Null is never returned. - * - * @param address - * @return authentication manager. - */ - public AuthenticationManager getAuthenticationManager(SocketAddress address); - - Map getAvailableAuthenticationManagers(); - - public static interface RegistryChangeListener - { - void authenticationManagerRegistered(AuthenticationManager authenticationManager); - void authenticationManagerUnregistered(AuthenticationManager authenticationManager); - } - - public void addRegistryChangeListener(RegistryChangeListener listener); - -} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java index d735ecb1d4..3c1b709648 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java @@ -20,10 +20,7 @@ package org.apache.qpid.server.security.auth.manager; import java.io.IOException; import java.security.Principal; -import java.util.Arrays; import java.util.HashMap; -import java.util.List; -import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; @@ -31,86 +28,15 @@ import javax.security.sasl.AuthorizeCallback; import javax.security.sasl.Sasl; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.UsernamePrincipal; public class KerberosAuthenticationManager implements AuthenticationManager { - private static final Logger _logger = Logger.getLogger(KerberosAuthenticationManager.class); - private static final String GSSAPI_MECHANISM = "GSSAPI"; private final CallbackHandler _callbackHandler = new GssApiCallbackHandler(); - public static class KerberosAuthenticationManagerConfiguration extends ConfigurationPlugin - { - - public static final ConfigurationPluginFactory FACTORY = - new ConfigurationPluginFactory() - { - public List getParentPaths() - { - return Arrays.asList("security.kerberos-auth-manager"); - } - - public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException - { - final ConfigurationPlugin instance = new KerberosAuthenticationManagerConfiguration(); - - instance.setConfiguration(path, config); - return instance; - } - }; - - public String[] getElementsProcessed() - { - return new String[0]; - } - - public void validateConfiguration() throws ConfigurationException - { - } - - } - - - public static final AuthenticationManagerPluginFactory FACTORY = new AuthenticationManagerPluginFactory() - { - public KerberosAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException - { - KerberosAuthenticationManagerConfiguration configuration = - config == null - ? null - : (KerberosAuthenticationManagerConfiguration) config.getConfiguration(KerberosAuthenticationManagerConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - _logger.info("No authentication-manager configuration found for KerberosAuthenticationManager"); - return null; - } - KerberosAuthenticationManager kerberosAuthenticationManager = new KerberosAuthenticationManager(); - kerberosAuthenticationManager.configure(configuration); - return kerberosAuthenticationManager; - } - - public Class getPluginClass() - { - return KerberosAuthenticationManager.class; - } - - public String getPluginName() - { - return KerberosAuthenticationManager.class.getName(); - } - }; - - - private KerberosAuthenticationManager() + KerberosAuthenticationManager() { } @@ -158,10 +84,7 @@ public class KerberosAuthenticationManager implements AuthenticationManager if (server.isComplete()) { - final Subject subject = new Subject(); - _logger.debug("Authenticated as " + server.getAuthorizationID()); - subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID())); - return new AuthenticationResult(subject); + return new AuthenticationResult(new UsernamePrincipal(server.getAuthorizationID())); } else { @@ -186,11 +109,6 @@ public class KerberosAuthenticationManager implements AuthenticationManager { } - @Override - public void configure(ConfigurationPlugin config) throws ConfigurationException - { - } - private static class GssApiCallbackHandler implements CallbackHandler { diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerFactory.java new file mode 100644 index 0000000000..7af6727280 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManagerFactory.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.util.Map; + +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; + +public class KerberosAuthenticationManagerFactory implements AuthenticationManagerFactory +{ + public static final String PROVIDER_TYPE = KerberosAuthenticationManager.class.getSimpleName(); + + @Override + public AuthenticationManager createInstance(Map attributes) + { + if (attributes != null && PROVIDER_TYPE.equals(attributes.get(ATTRIBUTE_TYPE))) + { + return new KerberosAuthenticationManager(); + } + return null; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PlainPasswordFileAuthenticationManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PlainPasswordFileAuthenticationManagerFactory.java new file mode 100644 index 0000000000..43b92735f1 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PlainPasswordFileAuthenticationManagerFactory.java @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; +import org.apache.qpid.server.security.auth.database.PrincipalDatabase; + +public class PlainPasswordFileAuthenticationManagerFactory extends AbstractPrincipalDatabaseAuthManagerFactory +{ + public static final String PROVIDER_TYPE = "PlainPasswordFileAuthenticationProvider"; + + @Override + String getType() + { + return PROVIDER_TYPE; + } + + @Override + PrincipalDatabase createPrincipalDatabase() + { + return new PlainPasswordFilePrincipalDatabase(); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java index e6498919a1..f4c834810d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java @@ -21,38 +21,25 @@ package org.apache.qpid.server.security.auth.manager; import java.security.Principal; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; -import org.apache.qpid.configuration.PropertyException; -import org.apache.qpid.configuration.PropertyUtils; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; import org.apache.qpid.server.security.auth.AuthenticationResult; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; 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.JCAProvider; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.UsernamePrincipal; -import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.AccountNotFoundException; import javax.security.sasl.Sasl; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import javax.security.sasl.SaslServerFactory; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; + import java.security.Security; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; -import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.TreeMap; @@ -60,27 +47,10 @@ import java.util.TreeMap; * Concrete implementation of the AuthenticationManager that determines if supplied * user credentials match those appearing in a PrincipalDatabase. The implementation * of the PrincipalDatabase is determined from the configuration. - * - * This implementation also registers the JMX UserManagemement MBean. - * - * This plugin expects configuration such as: - * - *
- * <pd-auth-manager>
- *   <principal-database>
- *      <class>org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase</class>
- *      <attributes>
- *         <attribute>
- *              <name>passwordFile</name>
- *              <value>${conf}/passwd</value>
- *          </attribute>
- *      </attributes>
- *   </principal-database>
- * </pd-auth-manager>
- * 
*/ public class PrincipalDatabaseAuthenticationManager implements AuthenticationManager { + private static final Logger _logger = Logger.getLogger(PrincipalDatabaseAuthenticationManager.class); /** The list of mechanisms, in the order in which they are configured (i.e. preferred order) */ @@ -95,95 +65,11 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan */ private final Map> _serverCreationProperties = new HashMap>(); - private PrincipalDatabase _principalDatabase = null; + private final PrincipalDatabase _principalDatabase; - public static final AuthenticationManagerPluginFactory FACTORY = new AuthenticationManagerPluginFactory() - { - public PrincipalDatabaseAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException - { - final PrincipalDatabaseAuthenticationManagerConfiguration configuration = - config == null - ? null - : (PrincipalDatabaseAuthenticationManagerConfiguration) config.getConfiguration(PrincipalDatabaseAuthenticationManagerConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - _logger.info("No authentication-manager configuration found for PrincipalDatabaseAuthenticationManager"); - return null; - } - - final PrincipalDatabaseAuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager(); - pdam.configure(configuration); - pdam.initialise(); - return pdam; - } - - public Class getPluginClass() - { - return PrincipalDatabaseAuthenticationManager.class; - } - - public String getPluginName() - { - return PrincipalDatabaseAuthenticationManager.class.getName(); - } - }; - - public static class PrincipalDatabaseAuthenticationManagerConfiguration extends ConfigurationPlugin { - - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public List getParentPaths() - { - return Arrays.asList("security.pd-auth-manager"); - } - - public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException - { - final ConfigurationPlugin instance = new PrincipalDatabaseAuthenticationManagerConfiguration(); - - instance.setConfiguration(path, config); - return instance; - } - }; - - public String[] getElementsProcessed() - { - return new String[] {"principal-database.class", - "principal-database.attributes.attribute.name", - "principal-database.attributes.attribute.value"}; - } - - public void validateConfiguration() throws ConfigurationException - { - } - - public String getPrincipalDatabaseClass() - { - return getConfig().getString("principal-database.class"); - } - - public Map getPdClassAttributeMap() throws ConfigurationException - { - final List argumentNames = (List) getConfig().getList("principal-database.attributes.attribute.name"); - final List argumentValues = (List) getConfig().getList("principal-database.attributes.attribute.value"); - final Map attributes = new HashMap(argumentNames.size()); - - for (int i = 0; i < argumentNames.size(); i++) - { - final String argName = argumentNames.get(i); - final String argValue = argumentValues.get(i); - - attributes.put(argName, argValue); - } - - return Collections.unmodifiableMap(attributes); - } - } - - protected PrincipalDatabaseAuthenticationManager() + public PrincipalDatabaseAuthenticationManager(PrincipalDatabase pd) { + _principalDatabase = pd; } public void initialise() @@ -246,21 +132,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan _logger.info("Initialised " + mechanism + " SASL provider successfully"); } - /** - * @see org.apache.qpid.server.plugins.Plugin#configure(org.apache.qpid.server.configuration.plugins.ConfigurationPlugin) - */ - public void configure(final ConfigurationPlugin config) throws ConfigurationException - { - final PrincipalDatabaseAuthenticationManagerConfiguration pdamConfig = (PrincipalDatabaseAuthenticationManagerConfiguration) config; - final String pdClazz = pdamConfig.getPrincipalDatabaseClass(); - - _logger.info("PrincipalDatabase concrete implementation : " + pdClazz); - - _principalDatabase = createPrincipalDatabaseImpl(pdClazz); - - configPrincipalDatabase(_principalDatabase, pdamConfig); - } - public String getMechanisms() { return _mechanisms; @@ -268,8 +139,11 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException { - return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism), - _callbackHandlerMap.get(mechanism)); + Map properties = _serverCreationProperties.get(mechanism); + CallbackHandler callbackHandler = _callbackHandlerMap.get(mechanism); + + return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, properties, + callbackHandler); } /** @@ -284,9 +158,8 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan if (server.isComplete()) { - final Subject subject = new Subject(); - subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID())); - return new AuthenticationResult(subject); + final String userId = server.getAuthorizationID(); + return new AuthenticationResult(new UsernamePrincipal(userId)); } else { @@ -308,9 +181,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan { if (_principalDatabase.verifyPassword(username, password.toCharArray())) { - final Subject subject = new Subject(); - subject.getPrincipals().add(new UsernamePrincipal(username)); - return new AuthenticationResult(subject); + return new AuthenticationResult(new UsernamePrincipal(username)); } else { @@ -329,100 +200,8 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan Security.removeProvider(PROVIDER_NAME); } - private PrincipalDatabase createPrincipalDatabaseImpl(final String pdClazz) throws ConfigurationException - { - try - { - return (PrincipalDatabase) Class.forName(pdClazz).newInstance(); - } - catch (InstantiationException ie) - { - throw new ConfigurationException("Cannot instantiate " + pdClazz, ie); - } - catch (IllegalAccessException iae) - { - throw new ConfigurationException("Cannot access " + pdClazz, iae); - } - catch (ClassNotFoundException cnfe) - { - throw new ConfigurationException("Cannot load " + pdClazz + " implementation", cnfe); - } - catch (ClassCastException cce) - { - throw new ConfigurationException("Expecting a " + PrincipalDatabase.class + " implementation", cce); - } - } - - private void configPrincipalDatabase(final PrincipalDatabase principalDatabase, final PrincipalDatabaseAuthenticationManagerConfiguration config) - throws ConfigurationException - { - - final Map attributes = config.getPdClassAttributeMap(); - - for (Iterator> iterator = attributes.entrySet().iterator(); iterator.hasNext();) - { - final Entry nameValuePair = iterator.next(); - final String methodName = generateSetterName(nameValuePair.getKey()); - final Method method; - try - { - method = principalDatabase.getClass().getMethod(methodName, String.class); - } - catch (Exception e) - { - 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", e); - } - try - { - method.invoke(principalDatabase, PropertyUtils.replaceProperties(nameValuePair.getValue())); - } - catch (IllegalArgumentException e) - { - throw new ConfigurationException(e.getMessage(), e); - } - catch (PropertyException e) - { - throw new ConfigurationException(e.getMessage(), e); - } - catch (IllegalAccessException e) - { - throw new ConfigurationException(e.getMessage(), e); - } - catch (InvocationTargetException e) - { - // QPID-1347.. InvocationTargetException wraps the checked exception thrown from the reflective - // method call. Pull out the underlying message and cause to make these more apparent to the user. - throw new ConfigurationException(e.getCause().getMessage(), e.getCause()); - } - } - } - public PrincipalDatabase getPrincipalDatabase() { return _principalDatabase; } - - private String generateSetterName(String argName) throws ConfigurationException - { - 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); - } - - final String methodName = "set" + argName; - return methodName; - } - - protected void setPrincipalDatabase(final PrincipalDatabase principalDatabase) - { - _principalDatabase = principalDatabase; - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java index 64b24e28bc..7891ef8cf5 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java @@ -21,10 +21,10 @@ package org.apache.qpid.server.security.auth.manager; import java.io.IOException; import java.security.Principal; -import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; -import java.util.List; + +import javax.naming.AuthenticationException; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; @@ -32,7 +32,6 @@ import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; -import javax.security.auth.Subject; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; @@ -41,13 +40,10 @@ import javax.security.sasl.AuthorizeCallback; import javax.security.sasl.Sasl; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback; public class SimpleLDAPAuthenticationManager implements AuthenticationManager @@ -55,123 +51,25 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager private static final Logger _logger = Logger.getLogger(SimpleLDAPAuthenticationManager.class); private static final String PLAIN_MECHANISM = "PLAIN"; - private static final String DEFAULT_LDAP_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; - private String _providerSearchURL; - private String _searchContext; - private String _searchFilter; - private String _providerAuthURL; - private String _ldapContextFactory; - - public static class SimpleLDAPAuthenticationManagerConfiguration extends ConfigurationPlugin - { - - public static final ConfigurationPluginFactory FACTORY = - new ConfigurationPluginFactory() - { - public List getParentPaths() - { - return Arrays.asList("security.simple-ldap-auth-manager"); - } - - public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException - { - final ConfigurationPlugin instance = new SimpleLDAPAuthenticationManagerConfiguration(); - - instance.setConfiguration(path, config); - return instance; - } - }; - - private static final String PROVIDER_URL = "provider-url"; - private static final String PROVIDER_SEARCH_URL = "provider-search-url"; - private static final String PROVIDER_AUTH_URL = "provider-auth-url"; - private static final String SEARCH_CONTEXT = "search-context"; - private static final String SEARCH_FILTER = "search-filter"; - private static final String LDAP_CONTEXT_FACTORY = "ldap-context-factory"; - - public String[] getElementsProcessed() - { - return new String[] {PROVIDER_URL, PROVIDER_SEARCH_URL, PROVIDER_AUTH_URL, SEARCH_CONTEXT, SEARCH_FILTER, - LDAP_CONTEXT_FACTORY}; - } - - public void validateConfiguration() throws ConfigurationException - { - } - - public String getLDAPContextFactory() - { - return getConfig().getString(LDAP_CONTEXT_FACTORY, DEFAULT_LDAP_CONTEXT_FACTORY); - } - - - public String getProviderURL() - { - return getConfig().getString(PROVIDER_URL); - } - - public String getProviderSearchURL() - { - return getConfig().getString(PROVIDER_SEARCH_URL, getProviderURL()); - } - - public String getSearchContext() - { - return getConfig().getString(SEARCH_CONTEXT); - } - - public String getSearchFilter() - { - return getConfig().getString(SEARCH_FILTER); - } - - public String getProviderAuthURL() - { - return getConfig().getString(PROVIDER_AUTH_URL, getProviderURL()); - } - } - - - public static final AuthenticationManagerPluginFactory FACTORY = new AuthenticationManagerPluginFactory() - { - public SimpleLDAPAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException - { - SimpleLDAPAuthenticationManagerConfiguration configuration = - config == null - ? null - : (SimpleLDAPAuthenticationManagerConfiguration) config.getConfiguration(SimpleLDAPAuthenticationManagerConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - _logger.info("No authentication-manager configuration found for SimpleLDAPAuthenticationManager"); - return null; - } - SimpleLDAPAuthenticationManager simpleLDAPAuthenticationManager = new SimpleLDAPAuthenticationManager(); - simpleLDAPAuthenticationManager.configure(configuration); - return simpleLDAPAuthenticationManager; - } - - public Class getPluginClass() - { - return SimpleLDAPAuthenticationManager.class; - } - - public String getPluginName() - { - return SimpleLDAPAuthenticationManager.class.getName(); - } - }; - + private final String _providerSearchURL; + private final String _providerAuthURL; + private final String _searchContext; + private final String _searchFilter; + private final String _ldapContextFactory; - private SimpleLDAPAuthenticationManager() + SimpleLDAPAuthenticationManager(String providerSearchUrl, String providerAuthUrl, String searchContext, String searchFilter, String ldapContextFactory) { + _providerSearchURL = providerSearchUrl; + _providerAuthURL = providerAuthUrl; + _searchContext = searchContext; + _searchFilter = searchFilter; + _ldapContextFactory = ldapContextFactory; } @Override public void initialise() { - + validateInitialDirContext(); } @Override @@ -205,10 +103,10 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager if (server.isComplete()) { - final Subject subject = new Subject(); - _logger.debug("Authenticated as " + server.getAuthorizationID()); - subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID())); - return new AuthenticationResult(subject); + String authorizationID = server.getAuthorizationID(); + _logger.debug("Authenticated as " + authorizationID); + + return new AuthenticationResult(new UsernamePrincipal(authorizationID)); } else { @@ -224,34 +122,74 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager @Override public AuthenticationResult authenticate(String username, String password) { - try { - return doLDAPNameAuthentication(getNameFromId(username), password); + AuthenticationResult result = doLDAPNameAuthentication(getNameFromId(username), password); + if(result.getStatus() == AuthenticationStatus.SUCCESS) + { + //Return a result based on the supplied username rather than the search name + return new AuthenticationResult(new UsernamePrincipal(username)); + } + else + { + return result; + } } catch (NamingException e) { - return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); - } } - private AuthenticationResult doLDAPNameAuthentication(String username, String password) throws NamingException + private AuthenticationResult doLDAPNameAuthentication(String name, String password) { + if(name == null) + { + //The search didn't return anything, class as not-authenticated before it NPEs below + return new AuthenticationResult(AuthenticationStatus.CONTINUE); + } + Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, _ldapContextFactory); env.put(Context.PROVIDER_URL, _providerAuthURL); env.put(Context.SECURITY_AUTHENTICATION, "simple"); - env.put(Context.SECURITY_PRINCIPAL, username); + env.put(Context.SECURITY_PRINCIPAL, name); env.put(Context.SECURITY_CREDENTIALS, password); - DirContext ctx = new InitialDirContext(env); - ctx.close(); - final Subject subject = new Subject(); - subject.getPrincipals().add(new UsernamePrincipal(username)); - return new AuthenticationResult(subject); + + DirContext ctx = null; + try + { + ctx = new InitialDirContext(env); + + //Authentication succeeded + return new AuthenticationResult(new UsernamePrincipal(name)); + } + catch(AuthenticationException ae) + { + //Authentication failed + return new AuthenticationResult(AuthenticationStatus.CONTINUE); + } + catch (NamingException e) + { + //Some other failure + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + finally + { + if(ctx != null) + { + try + { + ctx.close(); + } + catch (Exception e) + { + _logger.warn("Exception closing InitialDirContext", e); + } + } + } } @Override @@ -259,17 +197,8 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager { } - @Override - public void configure(ConfigurationPlugin config) throws ConfigurationException + private void validateInitialDirContext() { - SimpleLDAPAuthenticationManagerConfiguration ldapConfig = (SimpleLDAPAuthenticationManagerConfiguration) config; - - _ldapContextFactory = ldapConfig.getLDAPContextFactory(); - _providerSearchURL = ldapConfig.getProviderSearchURL(); - _providerAuthURL = ldapConfig.getProviderAuthURL(); - _searchContext = ldapConfig.getSearchContext(); - _searchFilter = ldapConfig.getSearchFilter(); - Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, _ldapContextFactory); env.put(Context.PROVIDER_URL, _providerSearchURL); @@ -277,11 +206,11 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager try { - new InitialDirContext(env); + new InitialDirContext(env).close(); } catch (NamingException e) { - throw new ConfigurationException("Unable to establish anonymous connection to the ldap server at " + _providerSearchURL, e); + throw new RuntimeException("Unable to establish anonymous connection to the ldap server at " + _providerSearchURL, e); } } @@ -305,19 +234,11 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager } catch (NamingException e) { - _logger.info("SASL Authentication Error", e); + _logger.warn("SASL Authentication Exception", e); } if(password != null) { - try - { - authenticated = doLDAPNameAuthentication(name, password); - - } - catch (NamingException e) - { - authenticated = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); - } + authenticated = doLDAPNameAuthentication(name, password); } } else if (callback instanceof PlainPasswordCallback) @@ -325,17 +246,10 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager password = ((PlainPasswordCallback)callback).getPlainPassword(); if(name != null) { - try - { - authenticated = doLDAPNameAuthentication(name, password); - if(authenticated.getStatus()== AuthenticationResult.AuthenticationStatus.SUCCESS) - { - ((PlainPasswordCallback)callback).setAuthenticated(true); - } - } - catch (NamingException e) + authenticated = doLDAPNameAuthentication(name, password); + if(authenticated.getStatus()== AuthenticationResult.AuthenticationStatus.SUCCESS) { - authenticated = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + ((PlainPasswordCallback)callback).setAuthenticated(true); } } } @@ -357,7 +271,6 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager env.put(Context.INITIAL_CONTEXT_FACTORY, _ldapContextFactory); env.put(Context.PROVIDER_URL, _providerSearchURL); - env.put(Context.SECURITY_AUTHENTICATION, "none"); DirContext ctx = null; @@ -382,7 +295,14 @@ public class SimpleLDAPAuthenticationManager implements AuthenticationManager } finally { - ctx.close(); + try + { + ctx.close(); + } + catch (Exception e) + { + _logger.warn("Exception closing InitialDirContext", e); + } } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactory.java new file mode 100644 index 0000000000..05a692fb0e --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactory.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.util.Map; + +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; + +public class SimpleLDAPAuthenticationManagerFactory implements AuthenticationManagerFactory +{ + private static final String DEFAULT_LDAP_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; + + public static final String PROVIDER_TYPE = SimpleLDAPAuthenticationManager.class.getSimpleName(); + + public static final String ATTRIBUTE_LDAP_CONTEXT_FACTORY = "ldapContextFactory"; + public static final String ATTRIBUTE_SEARCH_FILTER = "searchFilter"; + public static final String ATTRIBUTE_SEARCH_CONTEXT = "searchContext"; + public static final String ATTRIBUTE_PROVIDER_AUTH_URL = "providerAuthUrl"; + public static final String ATTRIBUTE_PROVIDER_SEARCH_URL = "providerSearchUrl"; + public static final String ATTRIBUTE_PROVIDER_URL = "providerUrl"; + + @Override + public AuthenticationManager createInstance(Map attributes) + { + if (attributes == null || !PROVIDER_TYPE.equals(attributes.get(ATTRIBUTE_TYPE))) + { + return null; + } + String providerUrl = (String) attributes.get(ATTRIBUTE_PROVIDER_URL); + String providerSearchUrl = (String) attributes.get(ATTRIBUTE_PROVIDER_SEARCH_URL); + if (providerSearchUrl == null) + { + providerSearchUrl = providerUrl; + } + String providerAuthUrl = (String) attributes.get(ATTRIBUTE_PROVIDER_AUTH_URL); + if (providerAuthUrl == null) + { + providerAuthUrl = providerUrl; + } + String searchContext = (String) attributes.get(ATTRIBUTE_SEARCH_CONTEXT); + String searchFilter = (String) attributes.get(ATTRIBUTE_SEARCH_FILTER); + String ldapContextFactory = (String) attributes.get(ATTRIBUTE_LDAP_CONTEXT_FACTORY); + if (ldapContextFactory == null) + { + ldapContextFactory = DEFAULT_LDAP_CONTEXT_FACTORY; + } + + return new SimpleLDAPAuthenticationManager(providerSearchUrl, providerAuthUrl, searchContext, searchFilter, + ldapContextFactory); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java index 2e21cfbb07..abb8677e90 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java @@ -22,13 +22,13 @@ package org.apache.qpid.server.security.auth.rmi; import java.net.SocketAddress; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import javax.management.remote.JMXAuthenticator; -import javax.management.remote.JMXPrincipal; import javax.security.auth.Subject; public class RMIPasswordAuthenticator implements JMXAuthenticator @@ -38,23 +38,33 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator static final String SHOULD_HAVE_2_ELEMENTS = "User details should have 2 elements, username, password"; static final String SHOULD_BE_NON_NULL = "Supplied username and password should be non-null"; static final String INVALID_CREDENTIALS = "Invalid user details supplied"; + static final String USER_NOT_AUTHORISED_FOR_MANAGEMENT = "User not authorised for management"; static final String CREDENTIALS_REQUIRED = "User details are required. " + - "Please ensure you are using an up to date management console to connect."; + "Please ensure you are using an up to date management console to connect."; - private AuthenticationManager _authenticationManager = null; - private SocketAddress _socketAddress; + private final Broker _broker; + private final SocketAddress _address; - public RMIPasswordAuthenticator(SocketAddress socketAddress) + public RMIPasswordAuthenticator(Broker broker, SocketAddress address) { - _socketAddress = socketAddress; + _broker = broker; + _address = address; } - public void setAuthenticationManager(final AuthenticationManager authenticationManager) + public Subject authenticate(Object credentials) throws SecurityException { - _authenticationManager = authenticationManager; + validateCredentials(credentials); + + final String[] userCredentials = (String[]) credentials; + final String username = (String) userCredentials[0]; + final String password = (String) userCredentials[1]; + + final Subject authenticatedSubject = doAuthentication(username, password); + doManagementAuthorisation(authenticatedSubject); + return authenticatedSubject; } - public Subject authenticate(Object credentials) throws SecurityException + private void validateCredentials(Object credentials) { // Verify that credential's are of type String[]. if (!(credentials instanceof String[])) @@ -70,41 +80,27 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator } // Verify that required number of credentials. - final String[] userCredentials = (String[]) credentials; - if (userCredentials.length != 2) + if (((String[])credentials).length != 2) { throw new SecurityException(SHOULD_HAVE_2_ELEMENTS); } + } - final String username = (String) userCredentials[0]; - final String password = (String) userCredentials[1]; - + private Subject doAuthentication(final String username, final String password) + { // Verify that all required credentials are actually present. if (username == null || password == null) { throw new SecurityException(SHOULD_BE_NON_NULL); } - // Verify that an AuthenticationManager has been set. - if (_authenticationManager == null) + SubjectCreator subjectCreator = _broker.getSubjectCreator(_address); + if (subjectCreator == null) { - try - { - if(ApplicationRegistry.getInstance().getAuthenticationManager(_socketAddress) != null) - { - _authenticationManager = ApplicationRegistry.getInstance().getAuthenticationManager(_socketAddress); - } - else - { - throw new SecurityException(UNABLE_TO_LOOKUP); - } - } - catch(IllegalStateException e) - { - throw new SecurityException(UNABLE_TO_LOOKUP); - } + throw new SecurityException("Can't get subject creator for " + _address); } - final AuthenticationResult result = _authenticationManager.authenticate(username, password); + + final SubjectAuthenticationResult result = subjectCreator.authenticate(username, password); if (AuthenticationStatus.ERROR.equals(result.getStatus())) { @@ -112,10 +108,7 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator } else if (AuthenticationStatus.SUCCESS.equals(result.getStatus())) { - final Subject subject = result.getSubject(); - subject.getPrincipals().add(new JMXPrincipal(username)); - subject.setReadOnly(); - return subject; + return result.getSubject(); } else { @@ -123,4 +116,21 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator } } + private void doManagementAuthorisation(Subject authenticatedSubject) + { + SecurityManager.setThreadSubject(authenticatedSubject); + try + { + if (!_broker.getSecurityManager().accessManagement()) + { + throw new SecurityException(USER_NOT_AUTHORISED_FOR_MANAGEMENT); + } + } + finally + { + SecurityManager.setThreadSubject(null); + } + } + + } \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java deleted file mode 100644 index 30a503c769..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java +++ /dev/null @@ -1,99 +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.sasl; - -import java.security.Principal; -import java.security.acl.Group; -import java.util.Enumeration; - -/** - * Immutable representation of a user group. In Qpid, groups do not know - * about their membership, and therefore the {@link #addMember(Principal)} - * methods etc throw {@link UnsupportedOperationException}. - * - */ -public class GroupPrincipal implements Group -{ - /** Name of the group */ - private final String _groupName; - - public GroupPrincipal(final String groupName) - { - _groupName = groupName; - } - - public String getName() - { - return _groupName; - } - - public boolean addMember(Principal user) - { - throw new UnsupportedOperationException("Not supported"); - } - - public boolean removeMember(Principal user) - { - throw new UnsupportedOperationException("Not supported"); - } - - public boolean isMember(Principal member) - { - throw new UnsupportedOperationException("Not supported"); - } - - public Enumeration members() - { - throw new UnsupportedOperationException("Not supported"); - } - - /** - * @see java.lang.Object#hashCode() - */ - public int hashCode() - { - final int prime = 37; - return prime * _groupName.hashCode(); - } - - /** - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - else - { - if (obj instanceof GroupPrincipal) - { - GroupPrincipal other = (GroupPrincipal) obj; - return _groupName.equals(other._groupName); - } - else - { - return false; - } - } - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java index f4e8f800c6..b70a987107 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePasswordInitialiser.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.security.auth.sasl; import org.apache.commons.configuration.Configuration; import org.apache.log4j.Logger; +import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.auth.database.PrincipalDatabase; import javax.security.auth.callback.Callback; diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java deleted file mode 100644 index 9e7db94216..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java +++ /dev/null @@ -1,99 +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.sasl; - -import javax.security.auth.Subject; -import java.security.Principal; -import java.util.Set; - -/** A principal that is just a wrapper for a simple username. */ -public class UsernamePrincipal implements Principal -{ - private final String _name; - - public UsernamePrincipal(String name) - { - if (name == null) - { - throw new IllegalArgumentException("name cannot be null"); - } - _name = name; - } - - public String getName() - { - return _name; - } - - public String toString() - { - return _name; - } - - /** - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() - { - final int prime = 31; - return prime * _name.hashCode(); - } - - /** - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - else - { - if (obj instanceof UsernamePrincipal) - { - UsernamePrincipal other = (UsernamePrincipal) obj; - return _name.equals(other._name); - } - else - { - return false; - } - } - } - - public static UsernamePrincipal getUsernamePrincipalFromSubject(final Subject authSubject) - { - if (authSubject == null) - { - throw new IllegalArgumentException("No authenticated subject."); - } - - final Set principals = authSubject.getPrincipals(UsernamePrincipal.class); - if (principals.size() != 1) - { - throw new IllegalArgumentException("Can't find single UsernamePrincipal in authenticated subject"); - } - return principals.iterator().next(); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java index 52d36023c2..d10193e743 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java @@ -23,6 +23,8 @@ package org.apache.qpid.server.security.auth.sasl.anonymous; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; +import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager; + public class AnonymousSaslServer implements SaslServer { @@ -52,7 +54,7 @@ public class AnonymousSaslServer implements SaslServer public String getAuthorizationID() { - return null; + return AnonymousAuthenticationManager.ANONYMOUS_PRINCIPAL.getName(); } public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java index 478f195530..4e12ac0750 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java @@ -139,6 +139,12 @@ public class CRAMMD5HexInitialiser extends UsernamePasswordInitialiser { _realPricipalDatabase.reload(); } + + @Override + public void setPasswordFile(String passwordFile) throws IOException + { + throw new UnsupportedOperationException(); + } } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupDatabase.java new file mode 100644 index 0000000000..c66e7fd4e4 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupDatabase.java @@ -0,0 +1,287 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.group; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Collections; +import java.util.Date; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListSet; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +/** + * A group database that reads/writes the following file format: + * + * group1.users=user1,user2 + * group2.users=user2,user3 + */ +public class FileGroupDatabase implements GroupDatabase +{ + private static final Logger LOGGER = Logger.getLogger(FileGroupDatabase.class); + + private Map> _groupToUserMap = new ConcurrentHashMap>(); + private Map> _userToGroupMap = new ConcurrentHashMap>(); + private String _groupFile; + + @Override + public Set getAllGroups() + { + return Collections.unmodifiableSet(_groupToUserMap.keySet()); + } + + public synchronized void setGroupFile(String groupFile) throws IOException + { + File file = new File(groupFile); + + if (!file.canRead()) + { + throw new FileNotFoundException(groupFile + + " cannot be found or is not readable"); + } + + readGroupFile(groupFile); + } + + @Override + public Set getUsersInGroup(String group) + { + if (group == null) + { + LOGGER.warn("Requested user set for null group. Returning empty set."); + return Collections.emptySet(); + } + + Set set = _groupToUserMap.get(group); + if (set == null) + { + return Collections.emptySet(); + } + else + { + return Collections.unmodifiableSet(set); + } + } + + @Override + public synchronized void addUserToGroup(String user, String group) + { + Set users = _groupToUserMap.get(group); + if (users == null) + { + throw new IllegalArgumentException("Group " + group + " does not exist so could not add " + user + " to it"); + } + + users.add(user); + + Set groups = _userToGroupMap.get(user); + if (groups == null) + { + groups = new ConcurrentSkipListSet(); + _userToGroupMap.put(user, groups); + } + groups.add(group); + + update(); + } + + @Override + public synchronized void removeUserFromGroup(String user, String group) + { + Set users = _groupToUserMap.get(group); + if (users == null) + { + throw new IllegalArgumentException("Group " + group + " does not exist so could not remove " + user + " from it"); + } + + users.remove(user); + + Set groups = _userToGroupMap.get(user); + if (groups != null) + { + groups.remove(group); + } + + update(); + } + + @Override + public Set getGroupsForUser(String user) + { + if(user == null) + { + LOGGER.warn("Requested group set for null user. Returning empty set."); + return Collections.emptySet(); + } + + Set groups = _userToGroupMap.get(user); + if (groups == null) + { + return Collections.emptySet(); + } + else + { + return Collections.unmodifiableSet(groups); + } + } + + @Override + public synchronized void createGroup(String group) + { + Set users = new ConcurrentSkipListSet(); + _groupToUserMap.put(group, users); + + update(); + } + + @Override + public synchronized void removeGroup(String group) + { + _groupToUserMap.remove(group); + for (Set groupsForUser : _userToGroupMap.values()) + { + groupsForUser.remove(group); + } + + update(); + } + + private synchronized void update() + { + if (_groupFile != null) + { + try + { + writeGroupFile(_groupFile); + } + catch (IOException e) + { + throw new RuntimeException("Unable to persist change to file " + _groupFile); + } + } + } + + private synchronized void readGroupFile(String groupFile) throws IOException + { + _groupFile = groupFile; + _groupToUserMap.clear(); + _userToGroupMap.clear(); + Properties propertiesFile = new Properties(); + FileInputStream fileInputStream = new FileInputStream(groupFile); + try + { + propertiesFile.load(fileInputStream); + } + finally + { + if(fileInputStream != null) + { + fileInputStream.close(); + } + } + + for (String propertyName : propertiesFile.stringPropertyNames()) + { + validatePropertyNameIsGroupName(propertyName); + + String groupName = propertyName.replaceAll("\\.users$", ""); + String userString = propertiesFile.getProperty(propertyName); + + final Set userSet = buildUserSetFromCommaSeparateValue(userString); + + _groupToUserMap.put(groupName, userSet); + + for (String userName : userSet) + { + Set groupsForThisUser = _userToGroupMap.get(userName); + + if (groupsForThisUser == null) + { + groupsForThisUser = new ConcurrentSkipListSet(); + _userToGroupMap.put(userName, groupsForThisUser); + } + + groupsForThisUser.add(groupName); + } + } + } + + private synchronized void writeGroupFile(String groupFile) throws IOException + { + Properties propertiesFile = new Properties(); + + for (String group : _groupToUserMap.keySet()) + { + Set users = _groupToUserMap.get(group); + String userList = StringUtils.join(users, ","); + + propertiesFile.setProperty(group + ".users", userList); + } + + String comment = "Written " + new Date(); + FileOutputStream fileOutputStream = new FileOutputStream(groupFile); + try + { + propertiesFile.store(fileOutputStream, comment); + } + finally + { + if(fileOutputStream != null) + { + fileOutputStream.close(); + } + } + } + + private void validatePropertyNameIsGroupName(String propertyName) + { + if (!propertyName.endsWith(".users")) + { + throw new IllegalArgumentException( + "Invalid definition with name '" + + propertyName + + "'. Group definitions must end with suffix '.users'"); + } + } + + private ConcurrentSkipListSet buildUserSetFromCommaSeparateValue(String userString) + { + String[] users = userString.split(","); + final ConcurrentSkipListSet userSet = new ConcurrentSkipListSet(); + for (String user : users) + { + final String trimmed = user.trim(); + if (!trimmed.isEmpty()) + { + userSet.add(trimmed); + } + } + return userSet; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java new file mode 100644 index 0000000000..8295f28f9e --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManager.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.group; + +import java.io.IOException; +import java.security.Principal; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.security.auth.UsernamePrincipal; + +/** + * Implementation of a group manager whose implementation is backed by a flat group file. + *

+ * This plugin is configured in the following manner: + *

+ *
+ * <file-group-manager>
+ *    <attributes>
+ *       <attribute>
+ *            <name>groupFile</name>
+ *            <value>${conf}/groups</value>
+ *        </attribute>
+ *    </attributes>
+ * </file-group-manager>
+ * 
+ */ +public class FileGroupManager implements GroupManager +{ + private final FileGroupDatabase _groupDatabase; + + + public FileGroupManager(String groupFile) + { + _groupDatabase = new FileGroupDatabase(); + try + { + _groupDatabase.setGroupFile(groupFile); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Unable to set group file " + groupFile, e); + } + } + + @Override + public Set getGroupPrincipalsForUser(String userId) + { + Set groups = _groupDatabase.getGroupsForUser(userId); + if (groups.isEmpty()) + { + return Collections.emptySet(); + } + else + { + Set principals = new HashSet(); + for (String groupName : groups) + { + principals.add(new GroupPrincipal(groupName)); + } + return principals; + } + } + + @Override + public Set getUserPrincipalsForGroup(String group) + { + Set users = _groupDatabase.getUsersInGroup(group); + if (users.isEmpty()) + { + return Collections.emptySet(); + } + else + { + Set principals = new HashSet(); + for (String user : users) + { + principals.add(new UsernamePrincipal(user)); + } + return principals; + } + } + + @Override + public Set getGroupPrincipals() + { + Set groups = _groupDatabase.getAllGroups(); + if (groups.isEmpty()) + { + return Collections.emptySet(); + } + else + { + Set principals = new HashSet(); + for (String groupName : groups) + { + principals.add(new GroupPrincipal(groupName)); + } + return principals; + } + } + + @Override + public void createGroup(String group) + { + _groupDatabase.createGroup(group); + } + + @Override + public void removeGroup(String group) + { + _groupDatabase.removeGroup(group); + } + + @Override + public void addUserToGroup(String user, String group) + { + _groupDatabase.addUserToGroup(user, group); + } + + @Override + public void removeUserFromGroup(String user, String group) + { + _groupDatabase.removeUserFromGroup(user, group); + + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java new file mode 100644 index 0000000000..5c4730a9c8 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/group/FileGroupManagerFactory.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.group; + +import static org.apache.qpid.server.util.MapValueConverter.getStringAttribute; + +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.plugin.GroupManagerFactory; + +public class FileGroupManagerFactory implements GroupManagerFactory +{ + static final String FILE_GROUP_MANAGER_TYPE = "file-group-manager"; + static final String FILE = "file"; + + @Override + public GroupManager createInstance(Map attributes) + { + if(!FILE_GROUP_MANAGER_TYPE.equals(getStringAttribute(GroupProvider.TYPE, attributes, null))) + { + return null; + } + + String groupFile = getStringAttribute(FILE, attributes, null); + if (StringUtils.isBlank(groupFile)) + { + throw new IllegalConfigurationException("Path to file containing groups is not specified!"); + } + return new FileGroupManager(groupFile); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupDatabase.java new file mode 100644 index 0000000000..98c12782d8 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupDatabase.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.group; + +import java.util.Set; + +public interface GroupDatabase +{ + Set getAllGroups(); + Set getUsersInGroup(String group); + + void addUserToGroup(String user, String group); + void removeUserFromGroup(String user, String group); + Set getGroupsForUser(String user); + void createGroup(String group); + void removeGroup(String group); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java new file mode 100644 index 0000000000..6d2df86919 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupManager.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.group; + +import java.security.Principal; +import java.util.Set; + +public interface GroupManager +{ + Set getGroupPrincipalsForUser(String user); + + Set getGroupPrincipals(); + + Set getUserPrincipalsForGroup(String group); + + void createGroup(String group); + + void removeGroup(String group); + + void addUserToGroup(String user, String group); + + void removeUserFromGroup(String user, String group); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupPrincipal.java b/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupPrincipal.java new file mode 100644 index 0000000000..a9590bb964 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupPrincipal.java @@ -0,0 +1,100 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.group; + +import java.io.Serializable; +import java.security.Principal; +import java.security.acl.Group; +import java.util.Enumeration; + +/** + * Immutable representation of a user group. In Qpid, groups do not know + * about their membership, and therefore the {@link #addMember(Principal)} + * methods etc throw {@link UnsupportedOperationException}. + * + */ +public class GroupPrincipal implements Group, Serializable +{ + /** Name of the group */ + private final String _groupName; + + public GroupPrincipal(final String groupName) + { + _groupName = groupName; + } + + public String getName() + { + return _groupName; + } + + public boolean addMember(Principal user) + { + throw new UnsupportedOperationException("Not supported"); + } + + public boolean removeMember(Principal user) + { + throw new UnsupportedOperationException("Not supported"); + } + + public boolean isMember(Principal member) + { + throw new UnsupportedOperationException("Not supported"); + } + + public Enumeration members() + { + throw new UnsupportedOperationException("Not supported"); + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() + { + final int prime = 37; + return prime * _groupName.hashCode(); + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + else + { + if (obj instanceof GroupPrincipal) + { + GroupPrincipal other = (GroupPrincipal) obj; + return _groupName.equals(other._groupName); + } + else + { + return false; + } + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupPrincipalAccessor.java b/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupPrincipalAccessor.java new file mode 100644 index 0000000000..d549b76aab --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/group/GroupPrincipalAccessor.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.server.security.group; + +import java.security.Principal; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.adapter.GroupProviderAdapter; + + +public class GroupPrincipalAccessor +{ + private final Collection _groupProviders; + + public GroupPrincipalAccessor(Collection groupProviders) + { + _groupProviders = groupProviders; + } + + public Set getGroupPrincipals(String username) + { + Set principals = new HashSet(); + for (GroupProvider groupProvider : _groupProviders) + { + Set groups = groupProvider.getGroupPrincipalsForUser(username); + if (groups != null) + { + principals.addAll(groups); + } + } + + return Collections.unmodifiableSet(principals); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java b/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java deleted file mode 100644 index bdcfd86f82..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.signal; - -import org.apache.log4j.Logger; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -public abstract class SignalHandlerTask -{ - private static final Logger LOGGER = Logger.getLogger(SignalHandlerTask.class); - - private static final String HANDLE_METHOD = "handle"; - private static final String SUN_MISC_SIGNAL_CLASS = "sun.misc.Signal"; - private static final String SUN_MISC_SIGNAL_HANDLER_CLASS = "sun.misc.SignalHandler"; - - public boolean register(final String signalName) - { - try - { - //try to load the signal handling classes - Class signalClazz = Class.forName(SUN_MISC_SIGNAL_CLASS); - Class handlerClazz = Class.forName(SUN_MISC_SIGNAL_HANDLER_CLASS); - - //create an InvocationHandler that just executes the SignalHandlerTask - InvocationHandler invoker = new InvocationHandler() - { - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable - { - handle(); - - return null; - } - }; - - //create a dynamic proxy implementing SignalHandler - Object handler = Proxy.newProxyInstance(handlerClazz.getClassLoader(), new Class[]{handlerClazz}, invoker); - - //create the Signal to handle - Constructor signalConstructor = signalClazz.getConstructor(String.class); - Object signal = signalConstructor.newInstance(signalName); - - //invoke the Signal.handle(signal, handler) method - Method handleMethod = signalClazz.getMethod(HANDLE_METHOD, signalClazz, handlerClazz); - handleMethod.invoke(null, signal, handler); - } - catch (Exception e) - { - LOGGER.debug("Unable to register handler for Signal " + signalName + " due to exception: " + e, e); - return false; - } - - return true; - } - - public abstract void handle(); - - public static String getPlatformDescription() - { - String name = System.getProperty("os.name"); - String osVer = System.getProperty("os.version"); - String jvmVendor = System.getProperty("java.vm.vendor"); - String jvmName = System.getProperty("java.vm.name"); - String javaRuntimeVer = System.getProperty("java.runtime.version"); - - return "OS: " + name + " " + osVer + ", JVM:" + jvmVendor + " " + jvmName + " " + javaRuntimeVer; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java b/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java index f352bbdd2c..ff41536a23 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java @@ -31,10 +31,10 @@ import org.apache.qpid.framing.MethodDispatcher; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import java.util.concurrent.CopyOnWriteArraySet; @@ -47,32 +47,29 @@ public class AMQStateManager implements AMQMethodListener { private static final Logger _logger = Logger.getLogger(AMQStateManager.class); - private final VirtualHostRegistry _virtualHostRegistry; + private final Broker _broker; private final AMQProtocolSession _protocolSession; /** The current state */ private AMQState _currentState; private CopyOnWriteArraySet _stateListeners = new CopyOnWriteArraySet(); - public AMQStateManager(VirtualHostRegistry virtualHostRegistry, AMQProtocolSession protocolSession) + public AMQStateManager(Broker broker, AMQProtocolSession protocolSession) { - - _virtualHostRegistry = virtualHostRegistry; + _broker = broker; _protocolSession = protocolSession; _currentState = AMQState.CONNECTION_NOT_STARTED; } /** - * Get the ApplicationRegistry associated with this AMQStateManager - * - * returns the application registry associated with the VirtualHostRegistry of the AMQStateManager + * Get the Broker instance * - * @return the ApplicationRegistry + * @return the Broker */ - public IApplicationRegistry getApplicationRegistry() + public Broker getBroker() { - return _virtualHostRegistry.getApplicationRegistry(); + return _broker; } public AMQState getCurrentState() @@ -148,7 +145,7 @@ public class AMQStateManager implements AMQMethodListener public VirtualHostRegistry getVirtualHostRegistry() { - return _virtualHostRegistry; + return _broker.getVirtualHostRegistry(); } public AMQProtocolSession getProtocolSession() @@ -157,13 +154,9 @@ public class AMQStateManager implements AMQMethodListener return _protocolSession; } - /** - * Get the AuthenticationManager associated with the ProtocolSession of the AMQStateManager - * - * @return the AuthenticationManager - */ - public AuthenticationManager getAuthenticationManager() + + public SubjectCreator getSubjectCreator() { - return getApplicationRegistry().getAuthenticationManager(getProtocolSession().getLocalAddress()); + return _broker.getSubjectCreator(getProtocolSession().getLocalAddress()); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java index ede01d247e..ab7ef3f55b 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java @@ -46,19 +46,7 @@ public interface ConfigurationRecoveryHandler public static interface BindingRecoveryHandler { void binding(UUID bindingId, UUID exchangeId, UUID queueId, String bindingName, ByteBuffer buf); - BrokerLinkRecoveryHandler completeBindingRecovery(); - } - - public static interface BrokerLinkRecoveryHandler - { - BridgeRecoveryHandler brokerLink(UUID id, long createTime, Map arguments); - void completeBrokerLinkRecovery(); - } - - public static interface BridgeRecoveryHandler - { - void bridge(UUID id, long createTime, Map arguments); - void completeBridgeRecoveryForLink(); + void completeBindingRecovery(); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java index 655887e5c2..4e7bbf04a6 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java @@ -26,8 +26,6 @@ import org.apache.qpid.AMQStoreException; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.federation.Bridge; -import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.queue.AMQQueue; public interface DurableConfigurationStore @@ -122,12 +120,5 @@ public interface DurableConfigurationStore * @throws AMQStoreException If the operation fails for any reason. */ void updateQueue(AMQQueue queue) throws AMQStoreException; - - void createBrokerLink(BrokerLink link) throws AMQStoreException; - - void deleteBrokerLink(BrokerLink link) throws AMQStoreException; - - void createBridge(Bridge bridge) throws AMQStoreException; - - void deleteBridge(Bridge bridge) throws AMQStoreException; + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java index 262d7d0213..3f1d1b9530 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java @@ -30,6 +30,7 @@ import java.util.concurrent.atomic.AtomicLong; /** A simple message store that stores the messages in a thread-safe structure in memory. */ public class MemoryMessageStore extends NullMessageStore { + public static final String TYPE = "Memory"; private final AtomicLong _messageId = new AtomicLong(1); private final AtomicBoolean _closed = new AtomicBoolean(false); @@ -138,6 +139,6 @@ public class MemoryMessageStore extends NullMessageStore @Override public String getStoreType() { - return "Memory"; + return TYPE; } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java new file mode 100644 index 0000000000..20b6b7a8a6 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + + +public class MemoryMessageStoreFactory implements MessageStoreFactory +{ + + @Override + public String getType() + { + return MemoryMessageStore.TYPE; + } + + @Override + public MessageStore createMessageStore() + { + return new MemoryMessageStore(); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java new file mode 100644 index 0000000000..0d5a4850f6 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java @@ -0,0 +1,66 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +public class MessageStoreCreator +{ + private Map _factories = new HashMap(); + + public MessageStoreCreator() + { + QpidServiceLoader qpidServiceLoader = new QpidServiceLoader(); + Iterable factories = qpidServiceLoader.atLeastOneInstanceOf(MessageStoreFactory.class); + for (MessageStoreFactory messageStoreFactory : factories) + { + String type = messageStoreFactory.getType(); + MessageStoreFactory factory = _factories.put(type.toLowerCase(), messageStoreFactory); + if (factory != null) + { + throw new IllegalStateException("MessageStoreFactory with type name '" + type + + "' is already registered using class '" + factory.getClass().getName() + "', can not register class '" + + messageStoreFactory.getClass().getName() + "'"); + } + } + } + + public MessageStore createMessageStore(String storeType) + { + MessageStoreFactory factory = _factories.get(storeType.toLowerCase()); + if (factory == null) + { + throw new IllegalConfigurationException("Unknown store type: " + storeType); + } + return factory.createMessageStore(); + } + + public Collection getFactories() + { + return Collections.unmodifiableCollection(_factories.values()); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java new file mode 100644 index 0000000000..a1afd02f12 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +public interface MessageStoreFactory +{ + String getType(); + + MessageStore createMessageStore(); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java index be08e309e6..c6bffbc1de 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java @@ -24,8 +24,6 @@ import org.apache.qpid.AMQStoreException; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.federation.Bridge; -import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.queue.AMQQueue; public abstract class NullMessageStore implements MessageStore @@ -77,26 +75,6 @@ public abstract class NullMessageStore implements MessageStore { } - @Override - public void createBrokerLink(final BrokerLink link) throws AMQStoreException - { - } - - @Override - public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException - { - } - - @Override - public void createBridge(final Bridge bridge) throws AMQStoreException - { - } - - @Override - public void deleteBridge(final Bridge bridge) throws AMQStoreException - { - } - @Override public void configureMessageStore(String name, MessageStoreRecoveryHandler recoveryHandler, diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/State.java b/java/broker/src/main/java/org/apache/qpid/server/store/State.java index 2783637b2a..1d0936cec4 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/State.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/State.java @@ -20,8 +20,6 @@ */ package org.apache.qpid.server.store; -import org.apache.qpid.server.configuration.ConfiguredObject; - public enum State { /** The initial state of the store. In practice, the store immediately transitions to the subsequent states. */ @@ -30,7 +28,7 @@ public enum State INITIALISING, /** * The initial set-up of the store has completed. - * If the store is persistent, it has not yet loaded configuration for {@link ConfiguredObject}'s from disk. + * If the store is persistent, it has not yet loaded configuration from disk. * * From the point of view of the user, the store is essentially stopped. */ diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java index 154d7e6535..e9946d1860 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.store.derby; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; @@ -41,7 +40,6 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; @@ -55,12 +53,9 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.federation.Bridge; -import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.store.ConfigurationRecoveryHandler; -import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler; import org.apache.qpid.server.store.ConfiguredObjectHelper; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.Event; @@ -236,7 +231,7 @@ public class DerbyMessageStore implements MessageStore private static final String DERBY_SINGLE_DB_SHUTDOWN_CODE = "08006"; - private static final String DERBY_STORE_TYPE = "DERBY"; + public static final String TYPE = "DERBY"; private final StateManager _stateManager; @@ -572,8 +567,7 @@ public class DerbyMessageStore implements MessageStore BindingRecoveryHandler brh = qrh.completeQueueRecovery(); _configuredObjectHelper.recoverBindings(brh, configuredObjects); - BrokerLinkRecoveryHandler lrh = brh.completeBindingRecovery(); - recoverBrokerLinks(lrh); + brh.completeBindingRecovery(); } catch (SQLException e) { @@ -581,144 +575,6 @@ public class DerbyMessageStore implements MessageStore } } - private void recoverBrokerLinks(final ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler lrh) - throws SQLException - { - _logger.info("Recovering broker links..."); - - Connection conn = null; - try - { - conn = newAutoCommitConnection(); - - PreparedStatement stmt = conn.prepareStatement(SELECT_ALL_FROM_LINKS); - - try - { - ResultSet rs = stmt.executeQuery(); - - try - { - - while(rs.next()) - { - UUID id = new UUID(rs.getLong(2), rs.getLong(1)); - long createTime = rs.getLong(3); - Blob argumentsAsBlob = rs.getBlob(4); - - byte[] dataAsBytes = argumentsAsBlob.getBytes(1,(int) argumentsAsBlob.length()); - - DataInputStream dis = new DataInputStream(new ByteArrayInputStream(dataAsBytes)); - int size = dis.readInt(); - - Map arguments = new HashMap(); - - for(int i = 0; i < size; i++) - { - arguments.put(dis.readUTF(), dis.readUTF()); - } - - ConfigurationRecoveryHandler.BridgeRecoveryHandler brh = lrh.brokerLink(id, createTime, arguments); - - recoverBridges(brh, id); - - } - } - catch (IOException e) - { - throw new SQLException(e.getMessage(), e); - } - finally - { - rs.close(); - } - } - finally - { - stmt.close(); - } - - } - finally - { - if(conn != null) - { - conn.close(); - } - } - - } - - private void recoverBridges(final ConfigurationRecoveryHandler.BridgeRecoveryHandler brh, final UUID linkId) - throws SQLException - { - _logger.info("Recovering bridges for link " + linkId + "..."); - - Connection conn = null; - try - { - conn = newAutoCommitConnection(); - - PreparedStatement stmt = conn.prepareStatement(SELECT_ALL_FROM_BRIDGES); - - try - { - stmt.setLong(1, linkId.getLeastSignificantBits()); - stmt.setLong(2, linkId.getMostSignificantBits()); - - ResultSet rs = stmt.executeQuery(); - - try - { - - while(rs.next()) - { - UUID id = new UUID(rs.getLong(2), rs.getLong(1)); - long createTime = rs.getLong(3); - Blob argumentsAsBlob = rs.getBlob(6); - - byte[] dataAsBytes = argumentsAsBlob.getBytes(1,(int) argumentsAsBlob.length()); - - DataInputStream dis = new DataInputStream(new ByteArrayInputStream(dataAsBytes)); - int size = dis.readInt(); - - Map arguments = new HashMap(); - - for(int i = 0; i < size; i++) - { - arguments.put(dis.readUTF(), dis.readUTF()); - } - - brh.bridge(id, createTime, arguments); - - } - brh.completeBridgeRecoveryForLink(); - } - catch (IOException e) - { - throw new SQLException(e.getMessage(), e); - } - finally - { - rs.close(); - } - } - finally - { - stmt.close(); - } - - } - finally - { - if(conn != null) - { - conn.close(); - } - } - - } - @Override public void close() throws Exception { @@ -975,71 +831,6 @@ public class DerbyMessageStore implements MessageStore } } - @Override - public void createBrokerLink(final BrokerLink link) throws AMQStoreException - { - _logger.debug("public void createBrokerLink(BrokerLink = " + link + "): called"); - - if (_stateManager.isInState(State.ACTIVE)) - { - try - { - Connection conn = newAutoCommitConnection(); - - PreparedStatement stmt = conn.prepareStatement(FIND_LINK); - try - { - - stmt.setLong(1, link.getQMFId().getLeastSignificantBits()); - stmt.setLong(2, link.getQMFId().getMostSignificantBits()); - ResultSet rs = stmt.executeQuery(); - try - { - - // If we don't have any data in the result set then we can add this queue - if (!rs.next()) - { - PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_LINKS); - - try - { - - insertStmt.setLong(1, link.getQMFId().getLeastSignificantBits()); - insertStmt.setLong(2, link.getQMFId().getMostSignificantBits()); - insertStmt.setLong(3, link.getCreateTime()); - - byte[] argumentBytes = convertStringMapToBytes(link.getArguments()); - ByteArrayInputStream bis = new ByteArrayInputStream(argumentBytes); - - insertStmt.setBinaryStream(4,bis,argumentBytes.length); - - insertStmt.execute(); - } - finally - { - insertStmt.close(); - } - } - } - finally - { - rs.close(); - } - } - finally - { - stmt.close(); - } - conn.close(); - - } - catch (SQLException e) - { - throw new AMQStoreException("Error writing " + link + " to database: " + e.getMessage(), e); - } - } - } - private byte[] convertStringMapToBytes(final Map arguments) throws AMQStoreException { byte[] argumentBytes; @@ -1072,139 +863,7 @@ public class DerbyMessageStore implements MessageStore return argumentBytes; } - @Override - public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException - { - _logger.debug("public void deleteBrokerLink( " + link + "): called"); - Connection conn = null; - PreparedStatement stmt = null; - try - { - conn = newAutoCommitConnection(); - stmt = conn.prepareStatement(DELETE_FROM_LINKS); - stmt.setLong(1, link.getQMFId().getLeastSignificantBits()); - stmt.setLong(2, link.getQMFId().getMostSignificantBits()); - int results = stmt.executeUpdate(); - - if (results == 0) - { - throw new AMQStoreException("Link " + link + " not found"); - } - } - catch (SQLException e) - { - throw new AMQStoreException("Error deleting Link " + link + " from database: " + e.getMessage(), e); - } - finally - { - closePreparedStatement(stmt); - closeConnection(conn); - } - - - } - - @Override - public void createBridge(final Bridge bridge) throws AMQStoreException - { - _logger.debug("public void createBridge(BrokerLink = " + bridge + "): called"); - if (_stateManager.isInState(State.ACTIVE)) - { - try - { - Connection conn = newAutoCommitConnection(); - - PreparedStatement stmt = conn.prepareStatement(FIND_BRIDGE); - try - { - - UUID id = bridge.getQMFId(); - stmt.setLong(1, id.getLeastSignificantBits()); - stmt.setLong(2, id.getMostSignificantBits()); - ResultSet rs = stmt.executeQuery(); - try - { - - // If we don't have any data in the result set then we can add this queue - if (!rs.next()) - { - PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_BRIDGES); - - try - { - - insertStmt.setLong(1, id.getLeastSignificantBits()); - insertStmt.setLong(2, id.getMostSignificantBits()); - - insertStmt.setLong(3, bridge.getCreateTime()); - - UUID linkId = bridge.getLink().getQMFId(); - insertStmt.setLong(4, linkId.getLeastSignificantBits()); - insertStmt.setLong(5, linkId.getMostSignificantBits()); - - byte[] argumentBytes = convertStringMapToBytes(bridge.getArguments()); - ByteArrayInputStream bis = new ByteArrayInputStream(argumentBytes); - - insertStmt.setBinaryStream(6,bis,argumentBytes.length); - - insertStmt.execute(); - } - finally - { - insertStmt.close(); - } - } - } - finally - { - rs.close(); - } - } - finally - { - stmt.close(); - } - conn.close(); - - } - catch (SQLException e) - { - throw new AMQStoreException("Error writing " + bridge + " to database: " + e.getMessage(), e); - } - } - } - - @Override - public void deleteBridge(final Bridge bridge) throws AMQStoreException - { - _logger.debug("public void deleteBridge( " + bridge + "): called"); - Connection conn = null; - PreparedStatement stmt = null; - try - { - conn = newAutoCommitConnection(); - stmt = conn.prepareStatement(DELETE_FROM_BRIDGES); - stmt.setLong(1, bridge.getQMFId().getLeastSignificantBits()); - stmt.setLong(2, bridge.getQMFId().getMostSignificantBits()); - int results = stmt.executeUpdate(); - - if (results == 0) - { - throw new AMQStoreException("Bridge " + bridge + " not found"); - } - } - catch (SQLException e) - { - throw new AMQStoreException("Error deleting bridge " + bridge + " from database: " + e.getMessage(), e); - } - finally - { - closePreparedStatement(stmt); - closeConnection(conn); - } - - } @Override public Transaction newTransaction() @@ -2134,8 +1793,9 @@ public class DerbyMessageStore implements MessageStore public ByteBuffer getContent(int offsetInMessage, int size) { ByteBuffer buf = ByteBuffer.allocate(size); - getContent(offsetInMessage, buf); + int length = getContent(offsetInMessage, buf); buf.position(0); + buf.limit(length); return buf; } @@ -2673,7 +2333,7 @@ public class DerbyMessageStore implements MessageStore @Override public String getStoreType() { - return DERBY_STORE_TYPE; + return TYPE; } } \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java new file mode 100644 index 0000000000..046b503d8a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store.derby; + +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.MessageStoreFactory; + +public class DerbyMessageStoreFactory implements MessageStoreFactory +{ + + @Override + public String getType() + { + return DerbyMessageStore.TYPE; + } + + @Override + public MessageStore createMessageStore() + { + return new DerbyMessageStore(); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java index c92853e400..6c5cb2e721 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java @@ -27,11 +27,6 @@ import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.SessionConfig; -import org.apache.qpid.server.configuration.SubscriptionConfig; -import org.apache.qpid.server.configuration.SubscriptionConfigType; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.filter.FilterManagerFactory; import org.apache.qpid.server.flow.FlowCreditManager; @@ -61,8 +56,7 @@ import java.util.concurrent.locks.ReentrantLock; * Encapsulation of a supscription to a queue.

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

*/ -public abstract class SubscriptionImpl implements Subscription, FlowCreditManager.FlowCreditManagerListener, - SubscriptionConfig +public abstract class SubscriptionImpl implements Subscription, FlowCreditManager.FlowCreditManagerListener { private StateListener _stateListener = new StateListener() @@ -91,7 +85,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private final long _subscriptionID; private LogSubject _logSubject; private LogActor _logActor; - private UUID _qmfId; private final AtomicLong _deliveredCount = new AtomicLong(0); private final AtomicLong _deliveredBytes = new AtomicLong(0); @@ -373,11 +366,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage return _channel; } - public ConfigStore getConfigStore() - { - return getQueue().getConfigStore(); - } - public Long getDelivered() { return _deliveredCount.get(); @@ -391,9 +379,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage } _queue = queue; - _qmfId = getConfigStore().createId(); - getConfigStore().addConfiguredObject(this); - _logSubject = new SubscriptionLogSubject(this); _logActor = new SubscriptionActor(CurrentActor.get().getRootMessageLogger(), this); @@ -547,8 +532,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage { _stateChangeLock.unlock(); } - getConfigStore().removeConfiguredObject(this); - //Log Subscription closed CurrentActor.get().message(_logSubject, SubscriptionMessages.CLOSE()); } @@ -752,11 +735,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage return "WINDOW"; } - public SessionConfig getSessionConfig() - { - return getChannel(); - } - public boolean isBrowsing() { return isBrowser(); @@ -767,32 +745,16 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage return true; } - @Override - public UUID getQMFId() - { - return _qmfId; - } - public boolean isDurable() { return false; } - public SubscriptionConfigType getConfigType() - { - return SubscriptionConfigType.getInstance(); - } - public boolean isExclusive() { return getQueue().hasExclusiveSubscriber(); } - public ConfiguredObject getParent() - { - return getSessionConfig(); - } - public String getName() { return String.valueOf(_consumerTag); diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java index dfd9315226..b9bba49fab 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java +++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java @@ -24,11 +24,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.SessionConfig; -import org.apache.qpid.server.configuration.SubscriptionConfig; -import org.apache.qpid.server.configuration.SubscriptionConfigType; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.flow.CreditCreditManager; @@ -86,7 +81,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener, SubscriptionConfig, LogSubject +public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener, LogSubject { private final long _subscriptionID; @@ -125,7 +120,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr private LogActor _logActor; private final Map _properties = new ConcurrentHashMap(); - private UUID _qmfId; private String _traceExclude; private String _trace; private final long _createTime = System.currentTimeMillis(); @@ -192,8 +186,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr Map arguments = queue.getArguments(); _traceExclude = (String) arguments.get("qpid.trace.exclude"); _trace = (String) arguments.get("qpid.trace.id"); - _qmfId = getConfigStore().createId(); - getConfigStore().addConfiguredObject(this); String filterLogString = null; _logActor = GenericActor.getInstance(this); @@ -283,7 +275,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } } _creditManager.removeListener(this); - getConfigStore().removeConfiguredObject(this); CurrentActor.get().message(getLogSubject(), SubscriptionMessages.CLOSE()); } finally @@ -295,11 +286,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } - public ConfigStore getConfigStore() - { - return getQueue().getConfigStore(); - } - public Long getDelivered() { return _deliveredCount.get(); @@ -970,12 +956,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return _session; } - - public SessionConfig getSessionConfig() - { - return getSessionModel(); - } - public boolean isBrowsing() { return _acquireMode == MessageAcquireMode.NOT_ACQUIRED; @@ -986,20 +966,11 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return getQueue().hasExclusiveSubscriber(); } - public ConfiguredObject getParent() - { - return getSessionConfig(); - } - public boolean isDurable() { return false; } - public SubscriptionConfigType getConfigType() - { - return SubscriptionConfigType.getInstance(); - } public boolean isExplicitAcknowledge() { @@ -1011,12 +982,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return _flowMode.toString(); } - @Override - public UUID getQMFId() - { - return _qmfId; - } - public String getName() { return _destination; diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java b/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java deleted file mode 100644 index 7c4188bfcd..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.transport; - -import org.apache.qpid.server.protocol.AmqpProtocolVersion; -import org.apache.qpid.transport.network.NetworkTransport; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -public class QpidAcceptor -{ - public enum Transport - { - TCP("TCP"), - SSL("TCP/SSL"); - - private final String _asString; - - Transport(String asString) - { - _asString = asString; - } - - public String toString() - { - return _asString; - } - } - - private NetworkTransport _networkTransport; - private Transport _transport; - private Set _supported; - - - public QpidAcceptor(NetworkTransport transport, Transport protocol, Set supported) - { - _networkTransport = transport; - _transport = protocol; - _supported = Collections.unmodifiableSet(new HashSet(supported)); - } - - public NetworkTransport getNetworkTransport() - { - return _networkTransport; - } - - public Transport getTransport() - { - return _transport; - } - - public Set getSupported() - { - return _supported; - } - - public String toString() - { - return _transport.toString(); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java index f21026794f..58de6a0cdf 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java @@ -20,17 +20,16 @@ */ package org.apache.qpid.server.transport; +import java.net.SocketAddress; import java.security.Principal; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; -import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import javax.security.auth.Subject; import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.configuration.ConnectionConfig; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -39,6 +38,7 @@ import org.apache.qpid.server.logging.messages.ConnectionMessages; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.security.AuthorizationHolder; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.Connection; @@ -48,6 +48,7 @@ import org.apache.qpid.transport.ExecutionException; import org.apache.qpid.transport.Method; import org.apache.qpid.transport.ProtocolEvent; import org.apache.qpid.transport.Session; +import org.apache.qpid.transport.network.NetworkConnection; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT; @@ -55,7 +56,6 @@ import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORM public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject, AuthorizationHolder { - private ConnectionConfig _config; private Runnable _onOpenTask; private AtomicBoolean _logClosed = new AtomicBoolean(false); private LogActor _actor = GenericActor.getInstance(this); @@ -69,6 +69,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel, private AtomicLong _lastIoTime = new AtomicLong(); private boolean _blocking; private Principal _peerPrincipal; + private NetworkConnection _networkConnection; public ServerConnection(final long connectionId) { @@ -147,16 +148,6 @@ public class ServerConnection extends Connection implements AMQConnectionModel, initialiseStatistics(); } - public void setConnectionConfig(final ConnectionConfig config) - { - _config = config; - } - - public ConnectionConfig getConfig() - { - return _config; - } - public void onOpen(final Runnable task) { _onOpenTask = task; @@ -228,7 +219,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel, MessageFormat.format(CONNECTION_FORMAT, getConnectionId(), getClientId(), - getConfig().getAddress(), + getRemoteAddressString(), getVirtualHost().getName()) + "] "; } @@ -238,7 +229,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel, MessageFormat.format(USER_FORMAT, getConnectionId(), getClientId(), - getConfig().getAddress()) + getRemoteAddressString()) + "] "; } @@ -247,7 +238,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel, return "[" + MessageFormat.format(SOCKET_FORMAT, getConnectionId(), - getConfig().getAddress()) + getRemoteAddressString()) + "] "; } } @@ -396,7 +387,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel, else { _authorizedSubject = authorizedSubject; - _authorizedPrincipal = authorizedSubject.getPrincipals().iterator().next(); + _authorizedPrincipal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(authorizedSubject); } } @@ -417,7 +408,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel, public String getRemoteAddressString() { - return getConfig().getAddress(); + return String.valueOf(getRemoteAddress()); } public String getUserName() @@ -489,4 +480,32 @@ public class ServerConnection extends Connection implements AMQConnectionModel, { _peerPrincipal = peerPrincipal; } + + @Override + public void setRemoteAddress(SocketAddress remoteAddress) + { + super.setRemoteAddress(remoteAddress); + } + + @Override + public void setLocalAddress(SocketAddress localAddress) + { + super.setLocalAddress(localAddress); + } + + public void setNetworkConnection(NetworkConnection network) + { + _networkConnection = network; + } + + public NetworkConnection getNetworkConnection() + { + return _networkConnection; + } + + public void doHeartbeat() + { + super.doHeartBeat(); + + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java index c13f63b44d..f3153fde62 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java @@ -32,18 +32,19 @@ import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import org.apache.qpid.common.ServerPropertyNames; import org.apache.qpid.properties.ConnectionStartProperties; -import org.apache.qpid.protocol.ProtocolEngine; -import org.apache.qpid.server.configuration.BrokerConfig; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import org.apache.qpid.server.subscription.Subscription_0_10; import org.apache.qpid.server.virtualhost.State; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.*; +import org.apache.qpid.transport.network.NetworkConnection; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,36 +54,49 @@ public class ServerConnectionDelegate extends ServerDelegate { private static final Logger LOGGER = LoggerFactory.getLogger(ServerConnectionDelegate.class); + private final Broker _broker; private final String _localFQDN; - private final IApplicationRegistry _appRegistry; private int _maxNoOfChannels; private Map _clientProperties; - private final AuthenticationManager _authManager; + private final SubjectCreator _subjectCreator; - public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN, AuthenticationManager authManager) + public ServerConnectionDelegate(Broker broker, String localFQDN, SubjectCreator subjectCreator) { - this(createConnectionProperties(appRegistry.getBrokerConfig()), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN, authManager); + this(createConnectionProperties(broker), Collections.singletonList((Object)"en_US"), broker, localFQDN, subjectCreator); } private ServerConnectionDelegate(Map properties, List locales, - IApplicationRegistry appRegistry, + Broker broker, String localFQDN, - AuthenticationManager authManager) + SubjectCreator subjectCreator) { - super(properties, parseToList(authManager.getMechanisms()), locales); + super(properties, parseToList(subjectCreator.getMechanisms()), locales); - _appRegistry = appRegistry; + _broker = broker; _localFQDN = localFQDN; - _maxNoOfChannels = appRegistry.getConfiguration().getMaxChannelCount(); - _authManager = authManager; + _maxNoOfChannels = (Integer)broker.getAttribute(Broker.SESSION_COUNT_LIMIT); + _subjectCreator = subjectCreator; + } + + private static List getFeatures(Broker broker) + { + String brokerDisabledFeatures = System.getProperty(BrokerProperties.PROPERTY_DISABLED_FEATURES); + final List features = new ArrayList(); + if (brokerDisabledFeatures == null || !brokerDisabledFeatures.contains(ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR)) + { + features.add(ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR); + } + + return Collections.unmodifiableList(features); } - private static Map createConnectionProperties(final BrokerConfig brokerConfig) + private static Map createConnectionProperties(final Broker broker) { final Map map = new HashMap(2); - map.put(ServerPropertyNames.FEDERATION_TAG, brokerConfig.getFederationTag()); - final List features = brokerConfig.getFeatures(); + // Federation tag is used by the client to identify the broker instance + map.put(ServerPropertyNames.FEDERATION_TAG, broker.getId().toString()); + final List features = getFeatures(broker); if (features != null && features.size() > 0) { map.put(ServerPropertyNames.QPID_FEATURES, features); @@ -112,14 +126,14 @@ public class ServerConnectionDelegate extends ServerDelegate protected SaslServer createSaslServer(Connection conn, String mechanism) throws SaslException { - return _authManager.createSaslServer(mechanism, _localFQDN, ((ServerConnection) conn).getPeerPrincipal()); + return _subjectCreator.createSaslServer(mechanism, _localFQDN, ((ServerConnection) conn).getPeerPrincipal()); } protected void secure(final SaslServer ss, final Connection conn, final byte[] response) { final ServerConnection sconn = (ServerConnection) conn; - final AuthenticationResult authResult = _authManager.authenticate(ss, response); + final SubjectAuthenticationResult authResult = _subjectCreator.authenticate(ss, response); if (AuthenticationStatus.SUCCESS.equals(authResult.getStatus())) { @@ -166,7 +180,7 @@ public class ServerConnectionDelegate extends ServerDelegate { vhostName = ""; } - vhost = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhostName); + vhost = _broker.getVirtualHostRegistry().getVirtualHost(vhostName); SecurityManager.setThreadSubject(sconn.getAuthorizedSubject()); @@ -174,7 +188,7 @@ public class ServerConnectionDelegate extends ServerDelegate { sconn.setVirtualHost(vhost); - if (!vhost.getSecurityManager().accessVirtualhost(vhostName, ((ProtocolEngine) sconn.getConfig()).getRemoteAddress())) + if (!vhost.getSecurityManager().accessVirtualhost(vhostName, sconn.getRemoteAddress())) { sconn.setState(Connection.State.CLOSING); sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, "Permission denied '"+vhostName+"'")); @@ -215,14 +229,18 @@ public class ServerConnectionDelegate extends ServerDelegate return; } - setConnectionTuneOkChannelMax(sconn, okChannelMax); - } + if(ok.hasHeartbeat()) + { + final int heartbeat = ok.getHeartbeat(); + if(heartbeat > 0) + { + final NetworkConnection networkConnection = sconn.getNetworkConnection(); + networkConnection.setMaxReadIdle(2 * heartbeat); + networkConnection.setMaxWriteIdle(heartbeat); + } + } - @Override - protected int getHeartbeatMax() - { - //TODO: implement broker support for actually sending heartbeats - return 0; + setConnectionTuneOkChannelMax(sconn, okChannelMax); } @Override diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java index f82b25b3d6..6152ddd228 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java @@ -42,13 +42,8 @@ import javax.security.auth.Subject; import org.apache.qpid.AMQException; import org.apache.qpid.AMQStoreException; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.server.TransactionTimeoutHelper; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.ConnectionConfig; -import org.apache.qpid.server.configuration.SessionConfig; -import org.apache.qpid.server.configuration.SessionConfigType; +import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -91,7 +86,7 @@ import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_F import static org.apache.qpid.util.Serial.gt; public class ServerSession extends Session - implements AuthorizationHolder, SessionConfig, + implements AuthorizationHolder, AMQSessionModel, LogSubject, AsyncAutoCommitTransaction.FutureRecorder { private static final Logger _logger = LoggerFactory.getLogger(ServerSession.class); @@ -100,8 +95,7 @@ public class ServerSession extends Session private static final int PRODUCER_CREDIT_TOPUP_THRESHOLD = 1 << 30; private static final int UNFINISHED_COMMAND_QUEUE_THRESHOLD = 500; - private final UUID _id; - private ConnectionConfig _connectionConfig; + private final UUID _id = UUID.randomUUID(); private long _createTime = System.currentTimeMillis(); private LogActor _actor = GenericActor.getInstance(this); @@ -139,7 +133,6 @@ public class ServerSession extends Session private final AtomicLong _txnCommits = new AtomicLong(0); private final AtomicLong _txnRejects = new AtomicLong(0); private final AtomicLong _txnCount = new AtomicLong(0); - private final AtomicLong _txnUpdateTime = new AtomicLong(0); private Map _subscriptions = new ConcurrentHashMap(); @@ -147,21 +140,21 @@ public class ServerSession extends Session private final TransactionTimeoutHelper _transactionTimeoutHelper; - ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry) - { - this(connection, delegate, name, expiry, ((ServerConnection)connection).getConfig()); - } - public ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry, ConnectionConfig connConfig) + public ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry) { super(connection, delegate, name, expiry); - _connectionConfig = connConfig; _transaction = new AsyncAutoCommitTransaction(this.getMessageStore(),this); _logSubject = new ChannelLogSubject(this); - _id = getConfigStore().createId(); - getConfigStore().addConfiguredObject(this); - _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject); + _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject, new CloseAction() + { + @Override + public void doTimeoutAction(String reason) throws AMQException + { + getConnectionModel().closeSession(ServerSession.this, AMQConstant.RESOURCE_ERROR, reason); + } + }); } protected void setState(State state) @@ -184,12 +177,6 @@ public class ServerSession extends Session invoke(new MessageStop("")); } - private ConfigStore getConfigStore() - { - return getConnectionConfig().getConfigStore(); - } - - @Override protected boolean isFull(int id) { @@ -206,9 +193,8 @@ public class ServerSession extends Session } getConnectionModel().registerMessageReceived(message.getSize(), message.getArrivalTime()); PostEnqueueAction postTransactionAction = new PostEnqueueAction(queues, message, isTransactional()) ; - _transaction.enqueue(queues,message, postTransactionAction, 0L); + _transaction.enqueue(queues,message, postTransactionAction); incrementOutstandingTxnsIfNecessary(); - updateTransactionalActivity(); } @@ -389,8 +375,6 @@ public class ServerSession extends Session } _messageDispositionListenerMap.clear(); - getConfigStore().removeConfiguredObject(this); - for (Task task : _taskList) { task.doTask(this); @@ -424,7 +408,6 @@ public class ServerSession extends Session entry.release(); } }); - updateTransactionalActivity(); } public Collection getSubscriptions() @@ -470,11 +453,6 @@ public class ServerSession extends Session return _transaction.isTransactional(); } - public boolean inTransaction() - { - return isTransactional() && _txnUpdateTime.get() > 0 && _transaction.getTransactionStartTime() > 0; - } - public void selectTx() { _transaction = new LocalTransaction(this.getMessageStore()); @@ -609,22 +587,6 @@ public class ServerSession extends Session } } - /** - * Update last transaction activity timestamp - */ - public void updateTransactionalActivity() - { - if (isTransactional()) - { - _txnUpdateTime.set(System.currentTimeMillis()); - } - } - - public Long getTxnStarts() - { - return _txnStarts.get(); - } - public Long getTxnCommits() { return _txnCommits.get(); @@ -682,23 +644,7 @@ public class ServerSession extends Session public VirtualHost getVirtualHost() { - return (VirtualHost) _connectionConfig.getVirtualHost(); - } - - @Override - public UUID getQMFId() - { - return _id; - } - - public SessionConfigType getConfigType() - { - return SessionConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return getVirtualHost(); + return getConnection().getVirtualHost(); } public boolean isDurable() @@ -706,44 +652,16 @@ public class ServerSession extends Session return false; } - public boolean isAttached() - { - return true; - } - - public long getDetachedLifespan() - { - return 0; - } - - public Long getExpiryTime() - { - return null; - } - - public Long getMaxClientRate() - { - return null; - } - - public ConnectionConfig getConnectionConfig() - { - return _connectionConfig; - } - - public String getSessionName() - { - return getName().toString(); - } public long getCreateTime() { return _createTime; } - public void mgmtClose() + @Override + public UUID getId() { - close(); + return _id; } public AMQConnectionModel getConnectionModel() @@ -774,28 +692,7 @@ public class ServerSession extends Session public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException { - if (inTransaction()) - { - long currentTime = System.currentTimeMillis(); - long openTime = currentTime - _transaction.getTransactionStartTime(); - long idleTime = currentTime - _txnUpdateTime.get(); - - _transactionTimeoutHelper.logIfNecessary(idleTime, idleWarn, ChannelMessages.IDLE_TXN(idleTime), - TransactionTimeoutHelper.IDLE_TRANSACTION_ALERT); - if (_transactionTimeoutHelper.isTimedOut(idleTime, idleClose)) - { - getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Idle transaction timed out"); - return; - } - - _transactionTimeoutHelper.logIfNecessary(openTime, openWarn, ChannelMessages.OPEN_TXN(openTime), - TransactionTimeoutHelper.OPEN_TRANSACTION_ALERT); - if (_transactionTimeoutHelper.isTimedOut(openTime, openClose)) - { - getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Open transaction timed out"); - return; - } - } + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, openWarn, openClose, idleWarn, idleClose); } public void block(AMQQueue queue) @@ -878,9 +775,7 @@ public class ServerSession extends Session ? getConnection().getConnectionId() : -1; - String remoteAddress = _connectionConfig instanceof ProtocolEngine - ? ((ProtocolEngine) _connectionConfig).getRemoteAddress().toString() - : ""; + String remoteAddress = String.valueOf(getConnection().getRemoteAddress()); return "[" + MessageFormat.format(CHANNEL_FORMAT, connectionId, @@ -1065,14 +960,16 @@ public class ServerSession extends Session super.setClose(close); } - public int compareTo(AMQSessionModel session) + @Override + public int getConsumerCount() { - return getQMFId().compareTo(session.getQMFId()); + return _subscriptions.values().size(); } @Override - public int getConsumerCount() + public int compareTo(AMQSessionModel o) { - return _subscriptions.values().size(); + return getId().compareTo(o.getId()); } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java index 05963ee874..d83bd1c4dc 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java @@ -31,7 +31,6 @@ import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeInUseException; import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.exchange.ExchangeType; import org.apache.qpid.server.exchange.HeadersExchange; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.filter.FilterManagerFactory; @@ -41,11 +40,11 @@ import org.apache.qpid.server.logging.messages.ExchangeMessages; import org.apache.qpid.server.message.MessageMetaData_0_10; import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; @@ -1266,18 +1265,12 @@ public class ServerSessionDelegate extends SessionDelegate } } queueRegistry.registerQueue(queue); - boolean autoRegister = ApplicationRegistry.getInstance().getConfiguration().getQueueAutoRegister(); - if (autoRegister) - { - - ExchangeRegistry exchangeRegistry = getExchangeRegistry(session); + ExchangeRegistry exchangeRegistry = getExchangeRegistry(session); - Exchange defaultExchange = exchangeRegistry.getDefaultExchange(); + Exchange defaultExchange = exchangeRegistry.getDefaultExchange(); - virtualHost.getBindingFactory().addBinding(queueName, queue, defaultExchange, null); - - } + virtualHost.getBindingFactory().addBinding(queueName, queue, defaultExchange, null); if (method.hasAutoDelete() && method.getAutoDelete() diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java index efd7850a49..43e60c8e13 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java @@ -66,11 +66,18 @@ public class AsyncAutoCommitTransaction implements ServerTransaction _futureRecorder = recorder; } + @Override public long getTransactionStartTime() { return 0L; } + @Override + public long getTransactionUpdateTime() + { + return 0L; + } + /** * Since AutoCommitTransaction have no concept of a long lived transaction, any Actions registered * by the caller are executed immediately. @@ -241,7 +248,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction } - public void enqueue(List queues, EnqueableMessage message, Action postTransactionAction, long currentTime) + public void enqueue(List queues, EnqueableMessage message, Action postTransactionAction) { Transaction txn = null; try diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java index e5a7df6880..8a9479a2d4 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java @@ -52,11 +52,18 @@ public class AutoCommitTransaction implements ServerTransaction _messageStore = transactionLog; } + @Override public long getTransactionStartTime() { return 0L; } + @Override + public long getTransactionUpdateTime() + { + return 0L; + } + /** * Since AutoCommitTransaction have no concept of a long lived transaction, any Actions registered * by the caller are executed immediately. @@ -178,7 +185,7 @@ public class AutoCommitTransaction implements ServerTransaction } - public void enqueue(List queues, EnqueableMessage message, Action postTransactionAction, long currentTime) + public void enqueue(List queues, EnqueableMessage message, Action postTransactionAction) { Transaction txn = null; try @@ -270,4 +277,6 @@ public class AutoCommitTransaction implements ServerTransaction } } + + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java index 05d0110e9b..ab987f0fb9 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DistributedTransaction.java @@ -26,7 +26,6 @@ import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.Transaction; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.Xid; @@ -39,10 +38,6 @@ public class DistributedTransaction implements ServerTransaction private final AutoCommitTransaction _autoCommitTransaction; - private volatile Transaction _transaction; - - private long _txnStartTime = 0L; - private DtxBranch _branch; private AMQSessionModel _session; private VirtualHost _vhost; @@ -55,9 +50,16 @@ public class DistributedTransaction implements ServerTransaction _autoCommitTransaction = new AutoCommitTransaction(vhost.getMessageStore()); } + @Override public long getTransactionStartTime() { - return _txnStartTime; + return 0; + } + + @Override + public long getTransactionUpdateTime() + { + return 0; } public void addPostTransactionAction(Action postTransactionAction) @@ -107,7 +109,7 @@ public class DistributedTransaction implements ServerTransaction { _branch.enqueue(queue, message); _branch.addPostTransactionAcion(postTransactionAction); - enqueue(Collections.singletonList(queue), message, postTransactionAction, System.currentTimeMillis()); + enqueue(Collections.singletonList(queue), message, postTransactionAction); } else { @@ -116,7 +118,7 @@ public class DistributedTransaction implements ServerTransaction } public void enqueue(List queues, EnqueableMessage message, - Action postTransactionAction, long currentTime) + Action postTransactionAction) { if(_branch != null) { @@ -128,7 +130,7 @@ public class DistributedTransaction implements ServerTransaction } else { - _autoCommitTransaction.enqueue(queues, message, postTransactionAction, currentTime); + _autoCommitTransaction.enqueue(queues, message, postTransactionAction); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java index 3fbcff7e2c..afa7cb0fb4 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java @@ -49,25 +49,42 @@ public class LocalTransaction implements ServerTransaction private final List _postTransactionActions = new ArrayList(); private volatile Transaction _transaction; - private MessageStore _transactionLog; - private long _txnStartTime = 0L; + private final ActivityTimeAccessor _activityTime; + private final MessageStore _transactionLog; + private volatile long _txnStartTime = 0L; + private volatile long _txnUpdateTime = 0l; private StoreFuture _asyncTran; public LocalTransaction(MessageStore transactionLog) { - _transactionLog = transactionLog; + this(transactionLog, new ActivityTimeAccessor() + { + @Override + public long getActivityTime() + { + return System.currentTimeMillis(); + } + }); } - - public boolean inTransaction() + + public LocalTransaction(MessageStore transactionLog, ActivityTimeAccessor activityTime) { - return _transaction != null; + _transactionLog = transactionLog; + _activityTime = activityTime; } + @Override public long getTransactionStartTime() { return _txnStartTime; } + @Override + public long getTransactionUpdateTime() + { + return _txnUpdateTime; + } + public void addPostTransactionAction(Action postTransactionAction) { sync(); @@ -78,6 +95,7 @@ public class LocalTransaction implements ServerTransaction { sync(); _postTransactionActions.add(postTransactionAction); + initTransactionStartTimeIfNecessaryAndAdvanceUpdateTime(); if(message.isPersistent() && queue.isDurable()) { @@ -104,6 +122,7 @@ public class LocalTransaction implements ServerTransaction { sync(); _postTransactionActions.add(postTransactionAction); + initTransactionStartTimeIfNecessaryAndAdvanceUpdateTime(); try { @@ -180,6 +199,7 @@ public class LocalTransaction implements ServerTransaction { sync(); _postTransactionActions.add(postTransactionAction); + initTransactionStartTimeIfNecessaryAndAdvanceUpdateTime(); if(message.isPersistent() && queue.isDurable()) { @@ -189,7 +209,7 @@ public class LocalTransaction implements ServerTransaction { _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getNameShortString()); } - + beginTranIfNecessary(); _transaction.enqueueMessage(queue, message); } @@ -202,15 +222,11 @@ public class LocalTransaction implements ServerTransaction } } - public void enqueue(List queues, EnqueableMessage message, Action postTransactionAction, long currentTime) + public void enqueue(List queues, EnqueableMessage message, Action postTransactionAction) { sync(); _postTransactionActions.add(postTransactionAction); - - if (_txnStartTime == 0L) - { - _txnStartTime = currentTime == 0L ? System.currentTimeMillis() : currentTime; - } + initTransactionStartTimeIfNecessaryAndAdvanceUpdateTime(); if(message.isPersistent()) { @@ -224,8 +240,7 @@ public class LocalTransaction implements ServerTransaction { _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getNameShortString() ); } - - + beginTranIfNecessary(); _transaction.enqueueMessage(queue, message); } @@ -378,16 +393,24 @@ public class LocalTransaction implements ServerTransaction } throw new RuntimeException("Failed to commit transaction", e); } - - } private void doPostTransactionActions() { + if(_logger.isDebugEnabled()) + { + _logger.debug("Beginning " + _postTransactionActions.size() + " post transaction actions"); + } + for(int i = 0; i < _postTransactionActions.size(); i++) { _postTransactionActions.get(i).postCommit(); } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Completed post transaction actions"); + } } public void rollback() @@ -427,16 +450,34 @@ public class LocalTransaction implements ServerTransaction } } + private void initTransactionStartTimeIfNecessaryAndAdvanceUpdateTime() + { + long currentTime = _activityTime.getActivityTime(); + + if (_txnStartTime == 0) + { + _txnStartTime = currentTime; + } + _txnUpdateTime = currentTime; + } + private void resetDetails() { _asyncTran = null; _transaction = null; - _postTransactionActions.clear(); + _postTransactionActions.clear(); _txnStartTime = 0L; + _txnUpdateTime = 0; } public boolean isTransactional() { return true; } + + public interface ActivityTimeAccessor + { + long getActivityTime(); + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java index c568ae67aa..8acac00479 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java @@ -55,11 +55,18 @@ public interface ServerTransaction /** * Return the time the current transaction started. - * + * * @return the time this transaction started or 0 if not in a transaction */ long getTransactionStartTime(); + /** + * Return the time of the last activity on the current transaction. + * + * @return the time of the last activity or 0 if not in a transaction + */ + long getTransactionUpdateTime(); + /** * Register an Action for execution after transaction commit or rollback. Actions * will be executed in the order in which they are registered. @@ -92,7 +99,7 @@ public interface ServerTransaction * * Store operations will result only for a persistent messages on durable queues. */ - void enqueue(List queues, EnqueableMessage message, Action postTransactionAction, long currentTime); + void enqueue(List queues, EnqueableMessage message, Action postTransactionAction); /** * Commit the transaction represented by this object. diff --git a/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java b/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java new file mode 100644 index 0000000000..aa7b4afcae --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/util/MapValueConverter.java @@ -0,0 +1,361 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.util; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class MapValueConverter +{ + + public static String getStringAttribute(String name, Map attributes, String defaultVal) + { + final Object value = attributes.get(name); + return toString(value, defaultVal); + } + + public static String toString(final Object value) + { + return toString(value, null); + } + + public static String toString(final Object value, String defaultVal) + { + if (value == null) + { + return defaultVal; + } + else if (value instanceof String) + { + return (String)value; + } + return String.valueOf(value); + } + + public static String getStringAttribute(String name, Map attributes) + { + assertMandatoryAttribute(name, attributes); + return getStringAttribute(name, attributes, null); + } + + private static void assertMandatoryAttribute(String name, Map attributes) + { + if (!attributes.containsKey(name)) + { + throw new IllegalArgumentException("Value for attribute " + name + " is not found"); + } + } + + public static Map getMapAttribute(String name, Map attributes, Map defaultVal) + { + final Object value = attributes.get(name); + if(value == null) + { + return defaultVal; + } + else if(value instanceof Map) + { + @SuppressWarnings("unchecked") + Map retVal = (Map) value; + return retVal; + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Map"); + } + } + + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static E getEnumAttribute(Class clazz, String name, Map attributes, E defaultVal) + { + Object obj = attributes.get(name); + if(obj == null) + { + return defaultVal; + } + else if(clazz.isInstance(obj)) + { + return (E) obj; + } + else if(obj instanceof String) + { + return (E) Enum.valueOf(clazz, (String)obj); + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type " + clazz.getSimpleName()); + } + } + + public static > E getEnumAttribute(Class clazz, String name, Map attributes) + { + assertMandatoryAttribute(name, attributes); + return getEnumAttribute(clazz, name, attributes, null); + } + + @SuppressWarnings({ "unchecked" }) + public static > T toEnum(String name, Object rawValue, Class enumType) + { + if (enumType.isInstance(rawValue)) + { + return (T) rawValue; + } + else if (rawValue instanceof String) + { + return (T) Enum.valueOf(enumType, (String) rawValue); + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type " + + enumType.getSimpleName()); + } + } + + public static Boolean getBooleanAttribute(String name, Map attributes, Boolean defaultValue) + { + Object obj = attributes.get(name); + return toBoolean(name, obj, defaultValue); + } + + public static Boolean toBoolean(String name, Object obj) + { + return toBoolean(name, obj, null); + } + + public static Boolean toBoolean(String name, Object obj, Boolean defaultValue) + { + if(obj == null) + { + return defaultValue; + } + else if(obj instanceof Boolean) + { + return (Boolean) obj; + } + else if(obj instanceof String) + { + return Boolean.parseBoolean((String) obj); + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Boolean"); + } + } + + + public static boolean getBooleanAttribute(String name, Map attributes) + { + assertMandatoryAttribute(name, attributes); + return getBooleanAttribute(name, attributes, null); + } + + public static Integer getIntegerAttribute(String name, Map attributes, Integer defaultValue) + { + Object obj = attributes.get(name); + return toInteger(name, obj, defaultValue); + } + + public static Integer toInteger(String name, Object obj) + { + return toInteger(name, obj, null); + } + + public static Integer toInteger(String name, Object obj, Integer defaultValue) + { + if(obj == null) + { + return defaultValue; + } + else if(obj instanceof Number) + { + return ((Number) obj).intValue(); + } + else if(obj instanceof String) + { + return Integer.valueOf((String) obj); + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Integer"); + } + } + + public static Integer getIntegerAttribute(String name, Map attributes) + { + assertMandatoryAttribute(name, attributes); + return getIntegerAttribute(name, attributes, null); + } + + public static Long getLongAttribute(String name, Map attributes, Long defaultValue) + { + Object obj = attributes.get(name); + return toLong(name, obj, defaultValue); + } + + public static Long toLong(String name, Object obj) + { + return toLong(name, obj, null); + } + + public static Long toLong(String name, Object obj, Long defaultValue) + { + if(obj == null) + { + return defaultValue; + } + else if(obj instanceof Number) + { + return ((Number) obj).longValue(); + } + else if(obj instanceof String) + { + return Long.valueOf((String) obj); + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Long"); + } + } + + public static Set getSetAttribute(String name, Map attributes) + { + assertMandatoryAttribute(name, attributes); + return getSetAttribute(name, attributes, Collections.emptySet()); + } + + @SuppressWarnings("unchecked") + public static Set getSetAttribute(String name, Map attributes, Set defaultValue) + { + Object obj = attributes.get(name); + if(obj == null) + { + return defaultValue; + } + else if(obj instanceof Set) + { + return (Set) obj; + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Set"); + } + } + + @SuppressWarnings("unchecked") + public static > Set getEnumSetAttribute(String name, Map attributes, Class clazz) + { + Object obj = attributes.get(name); + Object[] items = null; + if (obj == null) + { + return null; + } + else if (obj instanceof Collection) + { + Collection data = (Collection) obj; + items = data.toArray(new Object[data.size()]); + } + else if (obj instanceof String[]) + { + items = (String[]) obj; + } + else if (obj instanceof Object[]) + { + items = (Object[]) obj; + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + "[" + obj + + "] cannot be converted into set of enum of " + clazz); + } + Set set = new HashSet(); + for (int i = 0; i < items.length; i++) + { + T item = null; + Object value = items[i]; + if (value instanceof String) + { + item = (T) Enum.valueOf(clazz, (String) value); + } + else if (clazz.isInstance(value)) + { + item = (T) value; + } + else + { + throw new IllegalArgumentException("Cannot convert " + value + " from [" + obj + "] into enum of " + clazz + + " for attribute " + name); + } + set.add(item); + } + return set; + } + + @SuppressWarnings("unchecked") + public static Map convert(Map configurationAttributes, Map> attributeTypes) + { + Map attributes = new HashMap(); + for (Map.Entry> attributeEntry : attributeTypes.entrySet()) + { + String attributeName = attributeEntry.getKey(); + if (configurationAttributes.containsKey(attributeName)) + { + Class classObject = attributeEntry.getValue(); + Object rawValue = configurationAttributes.get(attributeName); + Object value = null; + if (classObject == Long.class || classObject == long.class) + { + value = toLong(attributeName, rawValue); + } + else if (classObject == Integer.class || classObject == int.class) + { + value = toInteger(attributeName, rawValue); + } + else if (classObject == Boolean.class || classObject == boolean.class) + { + value = toBoolean(attributeName, rawValue); + } + else if (classObject == String.class) + { + value = toString(rawValue); + } + else if (Enum.class.isAssignableFrom(classObject)) + { + @SuppressWarnings("rawtypes") + Class enumType = (Class)classObject; + value = toEnum(attributeName, rawValue, enumType); + } + else + { + throw new IllegalArgumentException("Cannot convert '" + rawValue + "' into " + classObject); + } + attributes.put(attributeName, value); + } + } + return attributes; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index f810360662..d24f79c56c 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java @@ -25,13 +25,10 @@ import java.util.UUID; import java.util.concurrent.ScheduledFuture; import org.apache.qpid.common.Closeable; import org.apache.qpid.server.binding.BindingFactory; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.VirtualHostConfig; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.protocol.v1_0.LinkRegistry; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.registry.IApplicationRegistry; @@ -41,7 +38,7 @@ import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.txn.DtxRegistry; -public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHostConfig, Closeable, StatisticsGatherer +public interface VirtualHost extends DurableConfigurationStore.Source, Closeable, StatisticsGatherer { IConnectionRegistry getConnectionRegistry(); @@ -61,8 +58,6 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo void close(); - UUID getBrokerId(); - UUID getId(); void scheduleHouseKeepingTask(long period, HouseKeepingTask task); @@ -77,25 +72,12 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo int getHouseKeepingActiveCount(); - IApplicationRegistry getApplicationRegistry(); + VirtualHostRegistry getVirtualHostRegistry(); BindingFactory getBindingFactory(); - void createBrokerConnection(String transport, - String host, - int port, - String vhost, - boolean durable, - String authMechanism, String username, String password); - - public BrokerLink createBrokerConnection(UUID id, long createTime, Map arguments); - - ConfigStore getConfigStore(); - DtxRegistry getDtxRegistry(); - void removeBrokerConnection(BrokerLink brokerLink); - LinkRegistry getLinkRegistry(String remoteContainerId); ScheduledFuture scheduleTask(long delay, Runnable timeoutTask); diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java index ea2f0f15e4..ae88e3e9f7 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java @@ -35,15 +35,16 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.BindingFactory; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.TransactionLogMessages; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.AbstractServerMessageImpl; import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.protocol.v1_0.Message_1_0; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.QueueEntry; @@ -65,7 +66,6 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa ConfigurationRecoveryHandler.QueueRecoveryHandler, ConfigurationRecoveryHandler.ExchangeRecoveryHandler, ConfigurationRecoveryHandler.BindingRecoveryHandler, - ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler, MessageStoreRecoveryHandler, MessageStoreRecoveryHandler.StoredMessageRecoveryHandler, TransactionLogRecoveryHandler, @@ -77,7 +77,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa private final VirtualHost _virtualHost; private final Map _queueRecoveries = new TreeMap(); - private final Map _recoveredMessages = new HashMap(); + private final Map _recoveredMessages = new HashMap(); private final Map _unusedMessages = new HashMap(); private MessageStoreLogSubject _logSubject; @@ -169,7 +169,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa public void message(StoredMessage message) { - AbstractServerMessageImpl serverMessage; + ServerMessage serverMessage; switch(message.getMetaData().getType()) { case META_DATA_0_8: @@ -178,6 +178,9 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa case META_DATA_0_10: serverMessage = new MessageTransferMessage(message, null); break; + case META_DATA_1_0: + serverMessage = new Message_1_0(message); + break; default: throw new RuntimeException("Unknown message type retrieved from store " + message.getMetaData().getClass()); } @@ -190,19 +193,6 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa { } - public BridgeRecoveryHandler brokerLink(final UUID id, - final long createTime, - final Map arguments) - { - BrokerLink blink = _virtualHost.createBrokerConnection(id, createTime, arguments); - return new BridgeRecoveryHandlerImpl(blink); - - } - - public void completeBrokerLinkRecovery() - { - } - public void dtxRecord(long format, byte[] globalId, byte[] branchId, Transaction.Record[] enqueues, Transaction.Record[] dequeues) @@ -221,12 +211,13 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa if(queue != null) { final long messageId = record.getMessage().getMessageNumber(); - final AbstractServerMessageImpl message = _recoveredMessages.get(messageId); + final ServerMessage message = _recoveredMessages.get(messageId); _unusedMessages.remove(messageId); if(message != null) { - message.incrementReference(); + final MessageReference ref = message.newReference(); + branch.enqueue(queue,message); @@ -239,7 +230,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa { queue.enqueue(message, true, null); - message.decrementReference(); + ref.release(); } catch (AMQException e) { @@ -251,7 +242,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa public void onRollback() { - message.decrementReference(); + ref.release(); } }); } @@ -280,7 +271,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa if(queue != null) { final long messageId = record.getMessage().getMessageNumber(); - final AbstractServerMessageImpl message = _recoveredMessages.get(messageId); + final ServerMessage message = _recoveredMessages.get(messageId); _unusedMessages.remove(messageId); if(message != null) @@ -412,9 +403,8 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa } - public BrokerLinkRecoveryHandler completeBindingRecovery() + public void completeBindingRecovery() { - return this; } public void complete() @@ -529,22 +519,4 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa } } - private class BridgeRecoveryHandlerImpl implements BridgeRecoveryHandler - { - private final BrokerLink _blink; - - public BridgeRecoveryHandlerImpl(final BrokerLink blink) - { - _blink = blink; - } - - public void bridge(final UUID id, final long createTime, final Map arguments) - { - _blink.createBridge(id, createTime, arguments); - } - - public void completeBridgeRecoveryForLink() - { - } - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java index d9dc0aa64e..dd3610373f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -35,12 +34,8 @@ import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.BindingFactory; -import org.apache.qpid.server.configuration.BrokerConfig; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; import org.apache.qpid.server.configuration.ExchangeConfiguration; import org.apache.qpid.server.configuration.QueueConfiguration; -import org.apache.qpid.server.configuration.VirtualHostConfigType; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.connection.ConnectionRegistry; import org.apache.qpid.server.connection.IConnectionRegistry; @@ -49,7 +44,6 @@ import org.apache.qpid.server.exchange.DefaultExchangeRegistry; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.VirtualHostMessages; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; @@ -61,17 +55,16 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.DefaultQueueRegistry; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.stats.StatisticsCounter; +import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.store.Event; import org.apache.qpid.server.store.EventListener; import org.apache.qpid.server.store.HAMessageStore; import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.MessageStoreCreator; import org.apache.qpid.server.store.OperationalLoggingListener; import org.apache.qpid.server.txn.DtxRegistry; -import org.apache.qpid.server.virtualhost.plugins.VirtualHostPlugin; -import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory; public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.RegistryChangeListener, EventListener { @@ -79,23 +72,19 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr private static final int HOUSEKEEPING_SHUTDOWN_TIMEOUT = 5; - private final UUID _qmfId; - private final String _name; private final UUID _id; private final long _createTime = System.currentTimeMillis(); - private final ConcurrentHashMap _links = new ConcurrentHashMap(); - private final ScheduledThreadPoolExecutor _houseKeepingTasks; - private final IApplicationRegistry _appRegistry; + private final VirtualHostRegistry _virtualHostRegistry; - private final SecurityManager _securityManager; + private final StatisticsGatherer _brokerStatisticsGatherer; - private final BrokerConfig _brokerConfig; + private final SecurityManager _securityManager; private final VirtualHostConfiguration _vhostConfig; @@ -120,7 +109,7 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr private final Map _linkRegistry = new HashMap(); private boolean _blocked; - public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig) throws Exception + public VirtualHostImpl(VirtualHostRegistry virtualHostRegistry, StatisticsGatherer brokerStatisticsGatherer, SecurityManager parentSecurityManager, VirtualHostConfiguration hostConfig) throws Exception { if (hostConfig == null) { @@ -132,19 +121,17 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr throw new IllegalArgumentException("Illegal name (" + hostConfig.getName() + ") for virtualhost."); } - _appRegistry = appRegistry; - _brokerConfig = _appRegistry.getBrokerConfig(); + _virtualHostRegistry = virtualHostRegistry; + _brokerStatisticsGatherer = brokerStatisticsGatherer; _vhostConfig = hostConfig; _name = _vhostConfig.getName(); _dtxRegistry = new DtxRegistry(); - _qmfId = _appRegistry.getConfigStore().createId(); _id = UUIDGenerator.generateVhostUUID(_name); CurrentActor.get().message(VirtualHostMessages.CREATED(_name)); - _securityManager = new SecurityManager(_appRegistry.getSecurityManager()); - _securityManager.configureHostPlugins(_vhostConfig); + _securityManager = new SecurityManager(parentSecurityManager, _vhostConfig.getConfig().getString("security.acl")); _connectionRegistry = new ConnectionRegistry(); _connectionRegistry.addRegistryChangeListener(this); @@ -154,13 +141,12 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr _queueRegistry = new DefaultQueueRegistry(this); _exchangeFactory = new DefaultExchangeFactory(this); - _exchangeFactory.initialise(_vhostConfig); _exchangeRegistry = new DefaultExchangeRegistry(this); _bindingFactory = new BindingFactory(this); - _messageStore = initialiseMessageStore(hostConfig.getMessageStoreClass()); + _messageStore = initialiseMessageStore(hostConfig); configureMessageStore(hostConfig); @@ -187,22 +173,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr return _id; } - @Override - public UUID getQMFId() - { - return _qmfId; - } - - public VirtualHostConfigType getConfigType() - { - return VirtualHostConfigType.getInstance(); - } - - public ConfiguredObject getParent() - { - return getBroker(); - } - public boolean isDurable() { return false; @@ -216,38 +186,9 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr */ private void initialiseHouseKeeping(long period) { - if (period != 0L) { scheduleHouseKeepingTask(period, new VirtualHostHouseKeepingTask()); - - Map plugins = _appRegistry.getPluginManager().getVirtualHostPlugins(); - - if (plugins != null) - { - for (Map.Entry entry : plugins.entrySet()) - { - String pluginName = entry.getKey(); - VirtualHostPluginFactory factory = entry.getValue(); - try - { - VirtualHostPlugin plugin = factory.newInstance(this); - - // If we had configuration for the plugin the schedule it. - if (plugin != null) - { - _houseKeepingTasks.scheduleAtFixedRate(plugin, plugin.getDelay() / 2, - plugin.getDelay(), plugin.getTimeUnit()); - - _logger.info("Loaded VirtualHostPlugin:" + plugin); - } - } - catch (RuntimeException e) - { - _logger.error("Unable to load VirtualHostPlugin:" + pluginName + " due to:" + e.getMessage(), e); - } - } - } } } @@ -329,19 +270,34 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr if (!(o instanceof MessageStore)) { - throw new ClassCastException("Message store factory class must implement " + MessageStore.class + + throw new ClassCastException("Message store class must implement " + MessageStore.class + ". Class " + clazz + " does not."); } final MessageStore messageStore = (MessageStore) o; - final MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, clazz.getSimpleName()); + return messageStore; + } + + private MessageStore initialiseMessageStore(VirtualHostConfiguration hostConfig) throws Exception + { + String storeType = hostConfig.getConfig().getString("store.type"); + MessageStore messageStore = null; + if (storeType == null) + { + messageStore = initialiseMessageStore(hostConfig.getMessageStoreClass()); + } + else + { + messageStore = new MessageStoreCreator().createMessageStore(storeType); + } + + final MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, messageStore.getClass().getSimpleName()); OperationalLoggingListener.listen(messageStore, storeLogSubject); messageStore.addEventListener(new BeforeActivationListener(), Event.BEFORE_ACTIVATE); messageStore.addEventListener(new AfterActivationListener(), Event.AFTER_ACTIVATE); messageStore.addEventListener(new BeforeCloseListener(), Event.BEFORE_CLOSE); messageStore.addEventListener(new BeforePassivationListener(), Event.BEFORE_PASSIVATE); - return messageStore; } @@ -468,16 +424,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr return _name; } - public BrokerConfig getBroker() - { - return _brokerConfig; - } - - public String getFederationTag() - { - return _brokerConfig.getFederationTag(); - } - public long getCreateTime() { return _createTime; @@ -534,14 +480,9 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr CurrentActor.get().message(VirtualHostMessages.CLOSED()); } - public UUID getBrokerId() - { - return _appRegistry.getBrokerId(); - } - - public IApplicationRegistry getApplicationRegistry() + public VirtualHostRegistry getVirtualHostRegistry() { - return _appRegistry; + return _virtualHostRegistry; } public BindingFactory getBindingFactory() @@ -553,14 +494,14 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr { _messagesDelivered.registerEvent(1L); _dataDelivered.registerEvent(messageSize); - _appRegistry.registerMessageDelivered(messageSize); + _brokerStatisticsGatherer.registerMessageDelivered(messageSize); } public void registerMessageReceived(long messageSize, long timestamp) { _messagesReceived.registerEvent(1L, timestamp); _dataReceived.registerEvent(messageSize, timestamp); - _appRegistry.registerMessageReceived(messageSize, timestamp); + _brokerStatisticsGatherer.registerMessageReceived(messageSize, timestamp); } public StatisticsCounter getMessageReceiptStatistics() @@ -604,51 +545,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr _dataReceived = new StatisticsCounter("bytes-received-" + getName()); } - public BrokerLink createBrokerConnection(UUID id, long createTime, Map arguments) - { - BrokerLink blink = new BrokerLink(this, id, createTime, arguments); - // TODO - cope with duplicate broker link creation requests - _links.putIfAbsent(blink,blink); - getConfigStore().addConfiguredObject(blink); - return blink; - } - - public void createBrokerConnection(final String transport, - final String host, - final int port, - final String vhost, - final boolean durable, - final String authMechanism, - final String username, - final String password) - { - BrokerLink blink = new BrokerLink(this, transport, host, port, vhost, durable, authMechanism, username, password); - - // TODO - cope with duplicate broker link creation requests - _links.putIfAbsent(blink,blink); - getConfigStore().addConfiguredObject(blink); - - } - - public void removeBrokerConnection(final String transport, - final String host, - final int port, - final String vhost) - { - removeBrokerConnection(new BrokerLink(this, transport, host, port, vhost, false, null,null,null)); - - } - - public void removeBrokerConnection(BrokerLink blink) - { - blink = _links.get(blink); - if(blink != null) - { - blink.close(); - getConfigStore().removeConfiguredObject(blink); - } - } - public synchronized LinkRegistry getLinkRegistry(String remoteContainerId) { LinkRegistry linkRegistry = _linkRegistry.get(remoteContainerId); @@ -660,11 +556,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr return linkRegistry; } - public ConfigStore getConfigStore() - { - return getApplicationRegistry().getConfigStore(); - } - public DtxRegistry getDtxRegistry() { return _dtxRegistry; diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java index 1be472844a..483e11942b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java @@ -1,140 +1,95 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.virtualhost; - -import org.apache.qpid.common.Closeable; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - - -public class VirtualHostRegistry implements Closeable -{ - private final Map _registry = new ConcurrentHashMap(); - - - private String _defaultVirtualHostName; - private ApplicationRegistry _applicationRegistry; - private final Collection _listeners = - Collections.synchronizedCollection(new ArrayList()); - - public VirtualHostRegistry(ApplicationRegistry applicationRegistry) - { - _applicationRegistry = applicationRegistry; - } - - public synchronized void registerVirtualHost(VirtualHost host) throws Exception - { - if(_registry.containsKey(host.getName())) - { - throw new Exception("Virtual Host with name " + host.getName() + " already registered."); - } - _registry.put(host.getName(),host); - synchronized (_listeners) +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhost; + +import org.apache.qpid.common.Closeable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +public class VirtualHostRegistry implements Closeable +{ + private final Map _registry = new ConcurrentHashMap(); + private String _defaultVirtualHostName; + + + public VirtualHostRegistry() + { + super(); + } + + public synchronized void registerVirtualHost(VirtualHost host) + { + if(_registry.containsKey(host.getName())) { - for(RegistryChangeListener listener : _listeners) - { - listener.virtualHostRegistered(host); - } + throw new IllegalArgumentException("Virtual Host with name " + host.getName() + " already registered."); } - } - - public synchronized void unregisterVirtualHost(VirtualHost host) - { - _registry.remove(host.getName()); - synchronized (_listeners) + _registry.put(host.getName(),host); + } + + public synchronized void unregisterVirtualHost(VirtualHost host) + { + _registry.remove(host.getName()); + } + + public VirtualHost getVirtualHost(String name) + { + if(name == null || name.trim().length() == 0 || "/".equals(name.trim())) { - for(RegistryChangeListener listener : _listeners) - { - listener.virtualHostUnregistered(host); - } + name = getDefaultVirtualHostName(); } - } - - public VirtualHost getVirtualHost(String name) - { - if(name == null || name.trim().length() == 0 || "/".equals(name.trim())) - { - name = getDefaultVirtualHostName(); - } - - return _registry.get(name); - } - - public VirtualHost getDefaultVirtualHost() - { - return getVirtualHost(getDefaultVirtualHostName()); - } - - private String getDefaultVirtualHostName() - { - return _defaultVirtualHostName; - } - - public void setDefaultVirtualHostName(String defaultVirtualHostName) - { - _defaultVirtualHostName = defaultVirtualHostName; - } - - - public Collection getVirtualHosts() - { - return new ArrayList(_registry.values()); - } - - public ApplicationRegistry getApplicationRegistry() - { - return _applicationRegistry; - } - - public ConfigStore getConfigStore() - { - return _applicationRegistry.getConfigStore(); - } - - public void close() - { - for (VirtualHost virtualHost : getVirtualHosts()) - { - virtualHost.close(); - } - - } - - public static interface RegistryChangeListener + + return _registry.get(name); + } + + public VirtualHost getDefaultVirtualHost() { - void virtualHostRegistered(VirtualHost virtualHost); - void virtualHostUnregistered(VirtualHost virtualHost); + return getVirtualHost(getDefaultVirtualHostName()); + } + private String getDefaultVirtualHostName() + { + return _defaultVirtualHostName; } - public void addRegistryChangeListener(RegistryChangeListener listener) + public void setDefaultVirtualHostName(String defaultVirtualHostName) { - _listeners.add(listener); + _defaultVirtualHostName = defaultVirtualHostName; + } + + + public Collection getVirtualHosts() + { + return new ArrayList(_registry.values()); + } + + public void close() + { + for (VirtualHost virtualHost : getVirtualHosts()) + { + virtualHost.close(); + } } -} +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/ConfiguredQueueBindingListener.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/ConfiguredQueueBindingListener.java deleted file mode 100644 index 12886f400a..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/ConfiguredQueueBindingListener.java +++ /dev/null @@ -1,105 +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.virtualhost.plugins; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionQueueConfiguration; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.Exchange.BindingListener; -import org.apache.qpid.server.queue.AMQQueue; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * This is a listener that caches queues that are configured for slow consumer disconnection. - * - * There should be one listener per virtual host, which can be added to all exchanges on - * that host. - * - * TODO In future, it will be possible to configure the policy at runtime, so only the queue - * itself is cached, and the configuration looked up by the housekeeping thread. This means - * that there may be occasions where the copy of the cache contents retrieved by the thread - * does not contain queues that are configured, or that configured queues are not present. - * - * @see BindingListener - */ -public class ConfiguredQueueBindingListener implements BindingListener -{ - private static final Logger _log = Logger.getLogger(ConfiguredQueueBindingListener.class); - - private String _vhostName; - private Set _cache = Collections.synchronizedSet(new HashSet()); - - public ConfiguredQueueBindingListener(String vhostName) - { - _vhostName = vhostName; - } - - /** - * @see BindingListener#bindingAdded(Exchange, Binding) - */ - public void bindingAdded(Exchange exchange, Binding binding) - { - processBinding(binding); - } - - /** - * @see BindingListener#bindingRemoved(Exchange, Binding) - */ - public void bindingRemoved(Exchange exchange, Binding binding) - { - processBinding(binding); - } - - private void processBinding(Binding binding) - { - AMQQueue queue = binding.getQueue(); - - SlowConsumerDetectionQueueConfiguration config = - queue.getConfiguration().getConfiguration(SlowConsumerDetectionQueueConfiguration.class.getName()); - if (config != null) - { - _cache.add(queue); - } - else - { - _cache.remove(queue); - } - } - - /** - * Lookup and return the cache of configured {@link AMQQueue}s. - * - * Note that when accessing the cached queues, the {@link java.util.Iterator} is not thread safe - * (see the {@link Collections#synchronizedSet(Set)} documentation) so a copy of the - * cache is returned. - * - * @return a copy of the cached {@link java.util.Set} of queues - */ - public Set getQueueCache() - { - return new HashSet(_cache); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java deleted file mode 100644 index bd2e30449a..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java +++ /dev/null @@ -1,174 +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.virtualhost.plugins; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionConfiguration; -import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionQueueConfiguration; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.plugins.logging.SlowConsumerDetectionMessages; -import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPlugin; - -import java.util.Set; -import java.util.concurrent.TimeUnit; - -public class SlowConsumerDetection extends VirtualHostHouseKeepingPlugin -{ - private SlowConsumerDetectionConfiguration _config; - private ConfiguredQueueBindingListener _listener; - - public static class SlowConsumerFactory implements VirtualHostPluginFactory - { - public SlowConsumerDetection newInstance(VirtualHost vhost) - { - SlowConsumerDetectionConfiguration config = vhost.getConfiguration().getConfiguration(SlowConsumerDetectionConfiguration.class.getName()); - - if (config == null) - { - return null; - } - - SlowConsumerDetection plugin = new SlowConsumerDetection(vhost); - plugin.configure(config); - return plugin; - } - } - - /** - * Configures the slow consumer disconnect plugin by adding a listener to each exchange on this - * virtual host to record all the configured queues in a cache for processing by the housekeeping - * thread. - * - * @see org.apache.qpid.server.plugins.Plugin#configure(ConfigurationPlugin) - */ - public void configure(ConfigurationPlugin config) - { - _config = (SlowConsumerDetectionConfiguration) config; - _listener = new ConfiguredQueueBindingListener(getVirtualHost().getName()); - final ExchangeRegistry exchangeRegistry = getVirtualHost().getExchangeRegistry(); - for (AMQShortString exchangeName : exchangeRegistry.getExchangeNames()) - { - exchangeRegistry.getExchange(exchangeName).addBindingListener(_listener); - } - } - - public SlowConsumerDetection(VirtualHost vhost) - { - super(vhost); - } - - public void execute() - { - CurrentActor.get().message(SlowConsumerDetectionMessages.RUNNING()); - - Set cache = _listener.getQueueCache(); - for (AMQQueue q : cache) - { - CurrentActor.get().message(SlowConsumerDetectionMessages.CHECKING_QUEUE(q.getName())); - - try - { - final SlowConsumerDetectionQueueConfiguration config = - q.getConfiguration().getConfiguration(SlowConsumerDetectionQueueConfiguration.class.getName()); - if (checkQueueStatus(q, config)) - { - final SlowConsumerPolicyPlugin policy = config.getPolicy(); - if (policy == null) - { - // We would only expect to see this during shutdown - getLogger().warn("No slow consumer policy for queue " + q.getName()); - } - else - { - policy.performPolicy(q); - } - - } - } - catch (Exception e) - { - // Don't throw exceptions as this will stop the house keeping task from running. - getLogger().error("Exception in SlowConsumersDetection for queue: " + q.getName(), e); - } - } - - CurrentActor.get().message(SlowConsumerDetectionMessages.COMPLETE()); - } - - public long getDelay() - { - return _config.getDelay(); - } - - public TimeUnit getTimeUnit() - { - return _config.getTimeUnit(); - } - - /** - * Check the depth,messageSize,messageAge,messageCount values for this q - * - * @param q the queue to check - * @param config the queue configuration to compare against the queue state - * - * @return true if the queue has reached a threshold. - */ - private boolean checkQueueStatus(AMQQueue q, SlowConsumerDetectionQueueConfiguration config) - { - if (config != null) - { - if (getLogger().isInfoEnabled()) - { - getLogger().info("Retrieved Queue(" + q.getName() + ") Config:" + config); - } - - int count = q.getMessageCount(); - - // First Check message counts - if ((config.getMessageCount() != 0 && count >= config.getMessageCount()) || - // The check queue depth - (config.getDepth() != 0 && q.getQueueDepth() >= config.getDepth()) || - // finally if we have messages on the queue check Arrival time. - // We must check count as OldestArrival time is Long.MAX_LONG when - // there are no messages. - (config.getMessageAge() != 0 && - ((count > 0) && q.getOldestMessageArrivalTime() >= config.getMessageAge()))) - { - - if (getLogger().isDebugEnabled()) - { - getLogger().debug("Detected Slow Consumer on Queue(" + q.getName() + ")"); - getLogger().debug("Queue Count:" + q.getMessageCount() + ":" + config.getMessageCount()); - getLogger().debug("Queue Depth:" + q.getQueueDepth() + ":" + config.getDepth()); - getLogger().debug("Queue Arrival:" + q.getOldestMessageArrivalTime() + ":" + config.getMessageAge()); - } - - return true; - } - } - return false; - } - -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostHouseKeepingPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostHouseKeepingPlugin.java deleted file mode 100644 index 191f8041d2..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostHouseKeepingPlugin.java +++ /dev/null @@ -1,61 +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.virtualhost.plugins; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.virtualhost.HouseKeepingTask; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import java.util.concurrent.TimeUnit; - -public abstract class VirtualHostHouseKeepingPlugin extends HouseKeepingTask implements VirtualHostPlugin -{ - private final Logger _logger = Logger.getLogger(getClass()); - - public VirtualHostHouseKeepingPlugin(VirtualHost vhost) - { - super(vhost); - } - - - /** - * Long value representing the delay between repeats - * - * @return - */ - public abstract long getDelay(); - - /** - * Option to specify what the delay value represents - * - * @return - * - * @see java.util.concurrent.TimeUnit for valid value. - */ - public abstract TimeUnit getTimeUnit(); - - - protected Logger getLogger() - { - return _logger; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostPlugin.java deleted file mode 100644 index 35f6228ab9..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostPlugin.java +++ /dev/null @@ -1,42 +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.virtualhost.plugins; - -import org.apache.qpid.server.plugins.Plugin; - -import java.util.concurrent.TimeUnit; - -public interface VirtualHostPlugin extends Runnable, Plugin -{ - /** - * Long value representing the delay between repeats - * - * @return - */ - public long getDelay(); - - /** - * Option to specify what the delay value represents - * @see java.util.concurrent.TimeUnit for valid value. - * @return - */ - public TimeUnit getTimeUnit(); -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostPluginFactory.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostPluginFactory.java deleted file mode 100644 index c8bea18444..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/VirtualHostPluginFactory.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.virtualhost.plugins; - -import org.apache.qpid.server.virtualhost.VirtualHost; - -public interface VirtualHostPluginFactory -{ - public VirtualHostHouseKeepingPlugin newInstance(VirtualHost vhost); -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/logging/SlowConsumerDetection_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/logging/SlowConsumerDetection_logmessages.properties deleted file mode 100644 index 03c56910c2..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/logging/SlowConsumerDetection_logmessages.properties +++ /dev/null @@ -1,23 +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. -# -# Default File used for all non-defined locales. - -RUNNING = SCD-1001 : Running -COMPLETE = SCD-1002 : Complete -CHECKING_QUEUE = SCD-1003 : Checking Status of Queue {0} \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/logging/TopicDeletePolicy_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/logging/TopicDeletePolicy_logmessages.properties deleted file mode 100644 index ed4fb1d45a..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/logging/TopicDeletePolicy_logmessages.properties +++ /dev/null @@ -1,22 +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. -# -# Default File used for all non-defined locales. - -DELETING_QUEUE = TDP-1001 : Deleting Queue -DISCONNECTING = TDP-1002 : Disconnecting Session \ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicy.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicy.java deleted file mode 100644 index f2f61f204e..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicy.java +++ /dev/null @@ -1,141 +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.virtualhost.plugins.policies; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.exchange.TopicExchange; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.virtualhost.plugins.logging.TopicDeletePolicyMessages; -import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPlugin; -import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPluginFactory; - -public class TopicDeletePolicy implements SlowConsumerPolicyPlugin -{ - private Logger _logger = Logger.getLogger(TopicDeletePolicy.class); - private TopicDeletePolicyConfiguration _configuration; - - public static class TopicDeletePolicyFactory implements SlowConsumerPolicyPluginFactory - { - public TopicDeletePolicy newInstance(ConfigurationPlugin configuration) throws ConfigurationException - { - TopicDeletePolicyConfiguration config = - configuration.getConfiguration(TopicDeletePolicyConfiguration.class.getName()); - - TopicDeletePolicy policy = new TopicDeletePolicy(); - policy.configure(config); - return policy; - } - - public String getPluginName() - { - return "topicdelete"; - } - - public Class getPluginClass() - { - return TopicDeletePolicy.class; - } - } - - public void performPolicy(AMQQueue q) - { - if (q == null) - { - return; - } - - AMQSessionModel owner = q.getExclusiveOwningSession(); - - // Only process exclusive queues - if (owner == null) - { - return; - } - - //Only process Topics - if (!validateQueueIsATopic(q)) - { - return; - } - - try - { - CurrentActor.get().message(owner.getLogSubject(),TopicDeletePolicyMessages.DISCONNECTING()); - // Close the consumer . this will cause autoDelete Queues to be purged - owner.getConnectionModel(). - closeSession(owner, AMQConstant.RESOURCE_ERROR, - "Consuming to slow."); - - // Actively delete non autoDelete queues if deletePersistent is set - if (!q.isAutoDelete() && (_configuration != null && _configuration.deletePersistent())) - { - CurrentActor.get().message(q.getLogSubject(), TopicDeletePolicyMessages.DELETING_QUEUE()); - q.delete(); - } - - } - catch (AMQException e) - { - _logger.warn("Unable to close consumer:" + owner + ", on queue:" + q.getName()); - } - - } - - /** - * Check the queue bindings to validate the queue is bound to the - * topic exchange. - * - * @param q the Queue - * - * @return true iff Q is bound to a TopicExchange - */ - private boolean validateQueueIsATopic(AMQQueue q) - { - for (Binding binding : q.getBindings()) - { - if (binding.getExchange() instanceof TopicExchange) - { - return true; - } - } - - return false; - } - - public void configure(ConfigurationPlugin config) - { - _configuration = (TopicDeletePolicyConfiguration) config; - } - - @Override - public String toString() - { - return "TopicDelete" + (_configuration == null ? "" : "[" + _configuration + "]"); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyConfiguration.java deleted file mode 100644 index 48158b7dff..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyConfiguration.java +++ /dev/null @@ -1,82 +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.virtualhost.plugins.policies; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; - -import java.util.Arrays; -import java.util.List; - -public class TopicDeletePolicyConfiguration extends ConfigurationPlugin -{ - - public static class TopicDeletePolicyConfigurationFactory - implements ConfigurationPluginFactory - { - public ConfigurationPlugin newInstance(String path, - Configuration config) - throws ConfigurationException - { - TopicDeletePolicyConfiguration slowConsumerConfig = - new TopicDeletePolicyConfiguration(); - slowConsumerConfig.setConfiguration(path, config); - return slowConsumerConfig; - } - - public List getParentPaths() - { - return Arrays.asList( - "virtualhosts.virtualhost.queues.slow-consumer-detection.policy.topicDelete", - "virtualhosts.virtualhost.queues.queue.slow-consumer-detection.policy.topicDelete", - "virtualhosts.virtualhost.topics.slow-consumer-detection.policy.topicDelete", - "virtualhosts.virtualhost.topics.topic.slow-consumer-detection.policy.topicDelete"); - } - } - - public String[] getElementsProcessed() - { - return new String[]{"delete-persistent"}; - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - // No validation required. - } - - public boolean deletePersistent() - { - // If we don't have configuration then we don't deletePersistent Queues - return (hasConfiguration() && contains("delete-persistent")); - } - - @Override - public String formatToString() - { - return (deletePersistent()?"delete-durable":""); - } - - -} diff --git a/java/broker/src/main/java/org/apache/qpid/slowconsumerdetection/policies/SlowConsumerPolicyPlugin.java b/java/broker/src/main/java/org/apache/qpid/slowconsumerdetection/policies/SlowConsumerPolicyPlugin.java deleted file mode 100644 index 7f600abdc9..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/slowconsumerdetection/policies/SlowConsumerPolicyPlugin.java +++ /dev/null @@ -1,29 +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.slowconsumerdetection.policies; - -import org.apache.qpid.server.plugins.Plugin; -import org.apache.qpid.server.queue.AMQQueue; - -public interface SlowConsumerPolicyPlugin extends Plugin -{ - public void performPolicy(AMQQueue Queue); -} diff --git a/java/broker/src/main/java/org/apache/qpid/slowconsumerdetection/policies/SlowConsumerPolicyPluginFactory.java b/java/broker/src/main/java/org/apache/qpid/slowconsumerdetection/policies/SlowConsumerPolicyPluginFactory.java deleted file mode 100644 index b2fe6766a6..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/slowconsumerdetection/policies/SlowConsumerPolicyPluginFactory.java +++ /dev/null @@ -1,27 +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.slowconsumerdetection.policies; - -import org.apache.qpid.server.plugins.PluginFactory; - -public interface SlowConsumerPolicyPluginFactory

extends PluginFactory

-{ -} diff --git a/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.configuration.ConfigurationStoreFactory b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.configuration.ConfigurationStoreFactory new file mode 100644 index 0000000000..5f75a8c4c9 --- /dev/null +++ b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.configuration.ConfigurationStoreFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.configuration.store.factory.JsonConfigurationStoreFactory diff --git a/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory new file mode 100644 index 0000000000..8ff67030ef --- /dev/null +++ b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory @@ -0,0 +1,24 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory +org.apache.qpid.server.security.auth.manager.Base64MD5PasswordFileAuthenticationManagerFactory +org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManagerFactory +org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManagerFactory +org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory +org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManagerFactory diff --git a/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ExchangeType b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ExchangeType new file mode 100644 index 0000000000..4ad646b7a0 --- /dev/null +++ b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ExchangeType @@ -0,0 +1,22 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.exchange.DirectExchangeType +org.apache.qpid.server.exchange.TopicExchangeType +org.apache.qpid.server.exchange.FanoutExchangeType +org.apache.qpid.server.exchange.HeadersExchangeType diff --git a/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.GroupManagerFactory b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.GroupManagerFactory new file mode 100644 index 0000000000..6bfb55ff18 --- /dev/null +++ b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.GroupManagerFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.security.group.FileGroupManagerFactory diff --git a/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.store.MessageStoreFactory b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.store.MessageStoreFactory new file mode 100644 index 0000000000..1357f816b7 --- /dev/null +++ b/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.store.MessageStoreFactory @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +org.apache.qpid.server.store.MemoryMessageStoreFactory \ No newline at end of file diff --git a/java/broker/src/main/resources/initial-store.json b/java/broker/src/main/resources/initial-store.json new file mode 100644 index 0000000000..a80ad95bd4 --- /dev/null +++ b/java/broker/src/main/resources/initial-store.json @@ -0,0 +1,58 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +{ + "name": "QpidBroker", + "defaultAuthenticationProvider" : "defaultAuthenticationProvider", + "defaultVirtualHost" : "default", + "authenticationproviders" : [ { + "name" : "defaultAuthenticationProvider", + "authenticationProviderType" : "PlainPasswordFileAuthenticationProvider", + "path" : "${QPID_HOME}/etc/passwd" + } ], + "ports" : [ { + "name" : "5672-AMQP", + "port" : 5672 + }, { + "name" : "8080-HTTP", + "port" : 8080, + "protocols" : [ "HTTP" ] + }, { + "name" : "8999-RMI", + "port" : 8999, + "protocols" : [ "RMI" ] + }, { + "name" : "9099-JMX_RMI", + "port" : 9099, + "protocols" : [ "JMX_RMI" ] + }], + "virtualhosts" : [ { + "name" : "default", + "storeType" : "DERBY", + "storePath" : "${QPID_WORK}/store" + } ], + "plugins" : [ { + "pluginType" : "MANAGEMENT-HTTP", + "name" : "httpManagement" + }, { + "pluginType" : "MANAGEMENT-JMX", + "name" : "jmxManagement" + } ] +} \ No newline at end of file diff --git a/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java b/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java index fc6cbcb248..e10bdbbb35 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java @@ -20,23 +20,69 @@ */ package org.apache.qpid.server; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.message.MessageContentSource; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; -public class AMQChannelTest extends InternalBrokerBaseCase +public class AMQChannelTest extends QpidTestCase { private VirtualHost _virtualHost; private AMQProtocolSession _protocolSession; + private Map _replies; + private Broker _broker; @Override public void setUp() throws Exception { super.setUp(); - _virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next(); - _protocolSession = new InternalTestProtocolSession(_virtualHost); + BrokerTestHelper.setUp(); + _virtualHost = BrokerTestHelper.createVirtualHost(getTestName()); + _broker = BrokerTestHelper.createBrokerMock(); + _protocolSession = new InternalTestProtocolSession(_virtualHost, _broker) + { + @Override + public void writeReturn(MessagePublishInfo messagePublishInfo, + ContentHeaderBody header, + MessageContentSource msgContent, + int channelId, + int replyCode, + AMQShortString replyText) throws AMQException + { + _replies.put(replyCode, replyText.asString()); + } + }; + _replies = new HashMap(); + } + + @Override + public void tearDown() throws Exception + { + try + { + _virtualHost.close(); + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } } public void testCompareTo() throws Exception @@ -44,9 +90,54 @@ public class AMQChannelTest extends InternalBrokerBaseCase AMQChannel channel1 = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore()); // create a channel with the same channelId but on a different session - AMQChannel channel2 = new AMQChannel(new InternalTestProtocolSession(_virtualHost), 1, _virtualHost.getMessageStore()); + AMQChannel channel2 = new AMQChannel(new InternalTestProtocolSession(_virtualHost, _broker), 1, _virtualHost.getMessageStore()); assertFalse("Unexpected compare result", channel1.compareTo(channel2) == 0); assertEquals("Unexpected compare result", 0, channel1.compareTo(channel1)); } + public void testPublishContentHeaderWhenMessageAuthorizationFails() throws Exception + { + setTestSystemProperty(BrokerProperties.PROPERTY_MSG_AUTH, "true"); + AMQChannel channel = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore()); + channel.setLocalTransactional(); + + MessagePublishInfo info = mock(MessagePublishInfo.class); + Exchange e = mock(Exchange.class); + ContentHeaderBody contentHeaderBody= mock(ContentHeaderBody.class); + BasicContentHeaderProperties properties = mock(BasicContentHeaderProperties.class); + + when(contentHeaderBody.getProperties()).thenReturn(properties); + when(info.getExchange()).thenReturn(new AMQShortString("test")); + when(properties.getUserId()).thenReturn(new AMQShortString(_protocolSession.getAuthorizedPrincipal().getName() + "_incorrect")); + + channel.setPublishFrame(info, e); + channel.publishContentHeader(contentHeaderBody); + channel.commit(); + + assertEquals("Unexpected number of replies", 1, _replies.size()); + assertEquals("Message authorization passed", "Access Refused", _replies.get(403)); + } + + public void testPublishContentHeaderWhenMessageAuthorizationPasses() throws Exception + { + setTestSystemProperty(BrokerProperties.PROPERTY_MSG_AUTH, "true"); + AMQChannel channel = new AMQChannel(_protocolSession, 1, _virtualHost.getMessageStore()); + channel.setLocalTransactional(); + + MessagePublishInfo info = mock(MessagePublishInfo.class); + Exchange e = mock(Exchange.class); + ContentHeaderBody contentHeaderBody= mock(ContentHeaderBody.class); + BasicContentHeaderProperties properties = mock(BasicContentHeaderProperties.class); + + when(contentHeaderBody.getProperties()).thenReturn(properties); + when(info.getExchange()).thenReturn(new AMQShortString("test")); + when(properties.getUserId()).thenReturn(new AMQShortString(_protocolSession.getAuthorizedPrincipal().getName())); + + channel.setPublishFrame(info, e); + channel.publishContentHeader(contentHeaderBody); + channel.commit(); + + assertEquals("Unexpected number of replies", 0, _replies.size()); + } + } diff --git a/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java b/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java index 43824e713f..16b459b5d4 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java @@ -22,91 +22,36 @@ package org.apache.qpid.server; import org.apache.qpid.test.utils.QpidTestCase; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - - public class BrokerOptionsTest extends QpidTestCase { private BrokerOptions _options; - - private static final int TEST_PORT1 = 6789; - private static final int TEST_PORT2 = 6790; - protected void setUp() { _options = new BrokerOptions(); } - - public void testDefaultPort() - { - assertEquals(Collections.emptySet(), _options.getPorts()); - } - public void testOverriddenPort() + public void testDefaultConfigurationStoreType() { - _options.addPort(TEST_PORT1); - assertEquals(Collections.singleton(TEST_PORT1), _options.getPorts()); + assertEquals("json", _options.getConfigurationStoreType()); } - public void testManyOverriddenPorts() + public void testOverriddenConfigurationStoreType() { - _options.addPort(TEST_PORT1); - _options.addPort(TEST_PORT2); - final Set expectedPorts = new HashSet(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); - assertEquals(expectedPorts, _options.getPorts()); + _options.setConfigurationStoreType("dby"); + assertEquals("dby", _options.getConfigurationStoreType()); } - public void testDuplicateOverriddenPortsAreSilentlyIgnored() + public void testDefaultConfigurationStoreLocation() { - _options.addPort(TEST_PORT1); - _options.addPort(TEST_PORT2); - _options.addPort(TEST_PORT1); // duplicate - should be silently ignored - final Set expectedPorts = new HashSet(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); - assertEquals(expectedPorts, _options.getPorts()); + assertNull(_options.getConfigurationStoreLocation()); } - public void testDefaultSSLPort() - { - assertEquals(Collections.emptySet(), _options.getSSLPorts()); - } - - public void testOverriddenSSLPort() - { - _options.addSSLPort(TEST_PORT1); - assertEquals(Collections.singleton(TEST_PORT1), _options.getSSLPorts()); - } - - public void testManyOverriddenSSLPorts() - { - _options.addSSLPort(TEST_PORT1); - _options.addSSLPort(TEST_PORT2); - final Set expectedPorts = new HashSet(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); - assertEquals(expectedPorts, _options.getSSLPorts()); - } - - public void testDuplicateOverriddenSSLPortsAreSilentlyIgnored() - { - _options.addSSLPort(TEST_PORT1); - _options.addSSLPort(TEST_PORT2); - _options.addSSLPort(TEST_PORT1); // duplicate - should be silently ignored - final Set expectedPorts = new HashSet(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); - assertEquals(expectedPorts, _options.getSSLPorts()); - } - - public void testDefaultConfigFile() - { - assertNull(_options.getConfigFile()); - } - - public void testOverriddenConfigFile() + public void testOverriddenConfigurationStoreLocation() { final String testConfigFile = "etc/mytestconfig.xml"; - _options.setConfigFile(testConfigFile); - assertEquals(testConfigFile, _options.getConfigFile()); + _options.setConfigurationStoreLocation(testConfigFile); + assertEquals(testConfigFile, _options.getConfigurationStoreLocation()); } public void testDefaultLogConfigFile() @@ -121,109 +66,85 @@ public class BrokerOptionsTest extends QpidTestCase assertEquals(testLogConfigFile, _options.getLogConfigFile()); } - public void testDefaultJmxPortRegistryServer() + public void testDefaultLogWatchFrequency() { - assertNull(_options.getJmxPortRegistryServer()); + assertEquals(0L, _options.getLogWatchFrequency()); } - public void testJmxPortRegistryServer() + public void testOverridenLogWatchFrequency() { - _options.setJmxPortRegistryServer(TEST_PORT1); - assertEquals(Integer.valueOf(TEST_PORT1), _options.getJmxPortRegistryServer()); + final int myFreq = 10 * 1000; + + _options.setLogWatchFrequency(myFreq); + assertEquals(myFreq, _options.getLogWatchFrequency()); } - public void testDefaultJmxPortConnectorServer() - { - assertNull(_options.getJmxPortConnectorServer()); - } - public void testJmxPortConnectorServer() + public void testDefaultInitialConfigurationStoreType() { - _options.setJmxPortConnectorServer(TEST_PORT1); - assertEquals(Integer.valueOf(TEST_PORT1), _options.getJmxPortConnectorServer()); + assertEquals("json", _options.getInitialConfigurationStoreType()); } - public void testQpidHomeExposesSysProperty() + public void testOverriddenInitialConfigurationStoreType() { - assertEquals(System.getProperty("QPID_HOME"), _options.getQpidHome()); - } - - public void testDefaultExcludesPortFor0_10() - { - assertEquals(Collections.EMPTY_SET, _options.getExcludedPorts(ProtocolExclusion.v0_10)); - } - - public void testOverriddenExcludesPortFor0_10() - { - _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT1); - assertEquals(Collections.singleton(TEST_PORT1), _options.getExcludedPorts(ProtocolExclusion.v0_10)); + _options.setInitialConfigurationStoreType("dby"); + assertEquals("dby", _options.getInitialConfigurationStoreType()); } - public void testManyOverriddenExcludedPortFor0_10() + public void testDefaultInitialConfigurationStoreLocation() { - _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT1); - _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT2); - final Set expectedPorts = new HashSet(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); - assertEquals(expectedPorts, _options.getExcludedPorts(ProtocolExclusion.v0_10)); + assertNull(_options.getInitialConfigurationStoreLocation()); } - public void testDuplicatedOverriddenExcludedPortFor0_10AreSilentlyIgnored() + public void testOverriddenInitialConfigurationStoreLocation() { - _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT1); - _options.addExcludedPort(ProtocolExclusion.v0_10, TEST_PORT2); - final Set expectedPorts = new HashSet(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); - assertEquals(expectedPorts, _options.getExcludedPorts(ProtocolExclusion.v0_10)); + final String testConfigFile = "etc/mytestconfig.xml"; + _options.setInitialConfigurationStoreLocation(testConfigFile); + assertEquals(testConfigFile, _options.getInitialConfigurationStoreLocation()); } - - public void testDefaultBind() + + public void testDefaultManagementMode() { - assertNull(_options.getBind()); + assertEquals(false, _options.isManagementMode()); } - - public void testOverriddenBind() + + public void testOverriddenDefaultManagementMode() { - final String bind = "192.168.0.1"; - _options.setBind(bind); - assertEquals(bind, _options.getBind()); + _options.setManagementMode(true); + assertEquals(true, _options.isManagementMode()); } - public void testDefaultLogWatchFrequency() + public void testDefaultManagementModeRmiPort() { - assertEquals(0L, _options.getLogWatchFrequency()); + assertEquals(0, _options.getManagementModeRmiPort()); } - public void testOverridenLogWatchFrequency() + public void testOverriddenDefaultManagementModeRmiPort() { - final int myFreq = 10 * 1000; - - _options.setLogWatchFrequency(myFreq); - assertEquals(myFreq, _options.getLogWatchFrequency()); + _options.setManagementModeRmiPort(5555); + assertEquals(5555, _options.getManagementModeRmiPort()); } - public void testDefaultIncludesPortFor0_10() + public void testDefaultManagementModeConnectorPort() { - assertEquals(Collections.EMPTY_SET, _options.getIncludedPorts(ProtocolInclusion.v0_10)); + assertEquals(0, _options.getManagementModeConnectorPort()); } - public void testOverriddenIncludesPortFor0_10() + public void testOverriddenDefaultManagementModeConnectorPort() { - _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT1); - assertEquals(Collections.singleton(TEST_PORT1), _options.getIncludedPorts(ProtocolInclusion.v0_10)); + _options.setManagementModeConnectorPort(5555); + assertEquals(5555, _options.getManagementModeConnectorPort()); } - public void testManyOverriddenIncludedPortFor0_10() + public void testDefaultManagementModeHttpPort() { - _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT1); - _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT2); - final Set expectedPorts = new HashSet(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); - assertEquals(expectedPorts, _options.getIncludedPorts(ProtocolInclusion.v0_10)); + assertEquals(0, _options.getManagementModeHttpPort()); } - public void testDuplicatedOverriddenIncludedPortFor0_10AreSilentlyIgnored() + public void testOverriddenDefaultManagementModeHttpPort() { - _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT1); - _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT2); - final Set expectedPorts = new HashSet(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); - assertEquals(expectedPorts, _options.getIncludedPorts(ProtocolInclusion.v0_10)); + _options.setManagementModeHttpPort(5555); + assertEquals(5555, _options.getManagementModeHttpPort()); } + } diff --git a/java/broker/src/test/java/org/apache/qpid/server/MainTest.java b/java/broker/src/test/java/org/apache/qpid/server/MainTest.java index ffd607574e..cab54b1310 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/MainTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/MainTest.java @@ -23,8 +23,6 @@ package org.apache.qpid.server; import org.apache.commons.cli.CommandLine; import org.apache.qpid.test.utils.QpidTestCase; -import java.util.EnumSet; - /** * Test to verify the command line parsing within the Main class, by * providing it a series of command line arguments and verifying the @@ -36,149 +34,135 @@ public class MainTest extends QpidTestCase { BrokerOptions options = startDummyMain(""); - assertTrue(options.getPorts().isEmpty()); - assertTrue(options.getSSLPorts().isEmpty()); - assertEquals(null, options.getJmxPortRegistryServer()); - assertEquals(null, options.getConfigFile()); + assertEquals("json", options.getConfigurationStoreType()); + assertEquals(null, options.getConfigurationStoreLocation()); assertEquals(null, options.getLogConfigFile()); - assertEquals(null, options.getBind()); - - for(ProtocolExclusion pe : EnumSet.allOf(ProtocolExclusion.class)) - { - assertEquals(0, options.getExcludedPorts(pe).size()); - } + assertEquals(0, options.getLogWatchFrequency()); + assertEquals("json", options.getInitialConfigurationStoreType()); + assertEquals(null, options.getInitialConfigurationStoreLocation()); - for(ProtocolInclusion pe : EnumSet.allOf(ProtocolInclusion.class)) - { - assertEquals(0, options.getIncludedPorts(pe).size()); - } + assertFalse(options.isManagementMode()); + assertEquals(0, options.getManagementModeConnectorPort()); + assertEquals(0, options.getManagementModeRmiPort()); + assertEquals(0, options.getManagementModeHttpPort()); } - public void testPortOverriddenSingle() + public void testConfigurationStoreLocation() { - BrokerOptions options = startDummyMain("-p 1234"); + BrokerOptions options = startDummyMain("-sp abcd/config.xml"); + assertEquals("abcd/config.xml", options.getConfigurationStoreLocation()); - assertTrue(options.getPorts().contains(1234)); - assertEquals(1, options.getPorts().size()); - assertTrue(options.getSSLPorts().isEmpty()); + options = startDummyMain("-store-path abcd/config2.xml"); + assertEquals("abcd/config2.xml", options.getConfigurationStoreLocation()); } - public void testPortOverriddenMultiple() + public void testConfigurationStoreType() { - BrokerOptions options = startDummyMain("-p 1234 -p 4321"); + BrokerOptions options = startDummyMain("-st dby"); + assertEquals("dby", options.getConfigurationStoreType()); - assertTrue(options.getPorts().contains(1234)); - assertTrue(options.getPorts().contains(4321)); - assertEquals(2, options.getPorts().size()); - assertTrue(options.getSSLPorts().isEmpty()); + options = startDummyMain("-store-type bdb"); + assertEquals("bdb", options.getConfigurationStoreType()); } - public void testSSLPortOverriddenSingle() + public void testLogConfig() { - BrokerOptions options = startDummyMain("-s 5678"); + BrokerOptions options = startDummyMain("-l wxyz/log4j.xml"); - assertTrue(options.getSSLPorts().contains(5678)); - assertEquals(1, options.getSSLPorts().size()); - assertTrue(options.getPorts().isEmpty()); + assertEquals("wxyz/log4j.xml", options.getLogConfigFile()); } - public void testSSLPortOverriddenMultiple() + public void testLogWatch() { - BrokerOptions options = startDummyMain("-s 5678 -s 8765"); + BrokerOptions options = startDummyMain("-w 9"); - assertTrue(options.getSSLPorts().contains(5678)); - assertTrue(options.getSSLPorts().contains(8765)); - assertEquals(2, options.getSSLPorts().size()); - assertTrue(options.getPorts().isEmpty()); + assertEquals(9, options.getLogWatchFrequency()); } - public void testNonSSLandSSLPortsOverridden() + public void testVersion() { - BrokerOptions options = startDummyMain("-p 5678 -s 8765"); + final TestMain main = new TestMain("-v".split("\\s")); - assertTrue(options.getPorts().contains(5678)); - assertTrue(options.getSSLPorts().contains(8765)); - assertEquals(1, options.getPorts().size()); - assertEquals(1, options.getSSLPorts().size()); + assertNotNull("Command line not parsed correctly", main.getCommandLine()); + assertTrue("Parsed command line didnt pick up version option", main.getCommandLine().hasOption("v")); } - public void testJmxPortRegistryServerOverridden() + public void testHelp() { - BrokerOptions options = startDummyMain("--jmxregistryport 3456"); - - assertEquals(Integer.valueOf(3456), options.getJmxPortRegistryServer()); + final TestMain main = new TestMain("-h".split("\\s")); - options = startDummyMain("-m 3457"); - assertEquals(Integer.valueOf(3457), options.getJmxPortRegistryServer()); + assertNotNull("Command line not parsed correctly", main.getCommandLine()); + assertTrue("Parsed command line didnt pick up help option", main.getCommandLine().hasOption("h")); } - public void testJmxPortConnectorServerOverridden() + public void testInitailConfigurationStoreLocation() { - BrokerOptions options = startDummyMain("--jmxconnectorport 3456"); + BrokerOptions options = startDummyMain("-isp abcd/config.xml"); + assertEquals("abcd/config.xml", options.getInitialConfigurationStoreLocation()); - assertEquals(Integer.valueOf(3456), options.getJmxPortConnectorServer()); + options = startDummyMain("-initial-store-path abcd/config.xml"); + assertEquals("abcd/config.xml", options.getInitialConfigurationStoreLocation()); } - public void testExclude0_10() + public void testInitialConfigurationStoreType() { - BrokerOptions options = startDummyMain("-p 3456 --exclude-0-10 3456"); + BrokerOptions options = startDummyMain("-ist dby"); + assertEquals("dby", options.getInitialConfigurationStoreType()); - assertTrue(options.getPorts().contains(3456)); - assertEquals(1, options.getPorts().size()); - assertTrue(options.getExcludedPorts(ProtocolExclusion.v0_10).contains(3456)); - assertEquals(1, options.getExcludedPorts(ProtocolExclusion.v0_10).size()); - assertEquals(0, options.getExcludedPorts(ProtocolExclusion.v0_9_1).size()); - } - - public void testConfig() - { - BrokerOptions options = startDummyMain("-c abcd/config.xml"); + options = startDummyMain("-initial-store-type bdb"); + assertEquals("bdb", options.getInitialConfigurationStoreType()); - assertEquals("abcd/config.xml", options.getConfigFile()); } - public void testLogConfig() + public void testManagementMode() { - BrokerOptions options = startDummyMain("-l wxyz/log4j.xml"); + BrokerOptions options = startDummyMain("-mm"); + assertTrue(options.isManagementMode()); - assertEquals("wxyz/log4j.xml", options.getLogConfigFile()); + options = startDummyMain("--management-mode"); + assertTrue(options.isManagementMode()); } - public void testLogWatch() + public void testManagementModeRmiPort() { - BrokerOptions options = startDummyMain("-w 9"); + BrokerOptions options = startDummyMain("-mm -rmi 7777"); + assertTrue(options.isManagementMode()); + assertEquals(7777, options.getManagementModeRmiPort()); - assertEquals(9, options.getLogWatchFrequency()); + options = startDummyMain("-mm --jmxregistryport 7777"); + assertTrue(options.isManagementMode()); + assertEquals(7777, options.getManagementModeRmiPort()); + + options = startDummyMain("-rmi 7777"); + assertEquals(0, options.getManagementModeRmiPort()); } - public void testVersion() + public void testManagementModeConnectorPort() { - final TestMain main = new TestMain("-v".split("\\s")); + BrokerOptions options = startDummyMain("-mm -jmxrmi 8888"); + assertTrue(options.isManagementMode()); + assertEquals(8888, options.getManagementModeConnectorPort()); - assertNotNull("Command line not parsed correctly", main.getCommandLine()); - assertTrue("Parsed command line didnt pick up version option", main.getCommandLine().hasOption("v")); + options = startDummyMain("-mm --jmxconnectorport 8888"); + assertTrue(options.isManagementMode()); + assertEquals(8888, options.getManagementModeConnectorPort()); + + options = startDummyMain("-jmxrmi 8888"); + assertEquals(0, options.getManagementModeConnectorPort()); } - public void testHelp() + public void testManagementModeHttpPort() { - final TestMain main = new TestMain("-h".split("\\s")); + BrokerOptions options = startDummyMain("-mm -http 9999"); + assertTrue(options.isManagementMode()); + assertEquals(9999, options.getManagementModeHttpPort()); - assertNotNull("Command line not parsed correctly", main.getCommandLine()); - assertTrue("Parsed command line didnt pick up help option", main.getCommandLine().hasOption("h")); - } + options = startDummyMain("-mm --httpport 9999"); + assertTrue(options.isManagementMode()); + assertEquals(9999, options.getManagementModeHttpPort()); - public void testInclude010() - { - BrokerOptions options = startDummyMain("-p 5678 --include-0-10 5678"); - - assertTrue(options.getPorts().contains(5678)); - assertEquals(1, options.getPorts().size()); - assertTrue(options.getIncludedPorts(ProtocolInclusion.v0_10).contains(5678)); - assertEquals(1, options.getIncludedPorts(ProtocolInclusion.v0_10).size()); - assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v0_9_1).size()); - assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v0_9).size()); - assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v0_8).size()); - assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v1_0).size()); + options = startDummyMain("-http 9999"); + assertEquals(0, options.getManagementModeHttpPort()); } private BrokerOptions startDummyMain(String commandLine) diff --git a/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java b/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java index 9081dc49d6..96078d766c 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java @@ -18,67 +18,131 @@ */ package org.apache.qpid.server; -import static org.mockito.Matchers.any; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.apache.qpid.server.logging.messages.ChannelMessages.IDLE_TXN_LOG_HIERARCHY; +import static org.apache.qpid.server.logging.messages.ChannelMessages.OPEN_TXN_LOG_HIERARCHY; +import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.same; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; +import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogMessage; import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.test.utils.QpidTestCase; +import org.hamcrest.Description; +import org.mockito.ArgumentMatcher; public class TransactionTimeoutHelperTest extends QpidTestCase { - private final LogMessage _logMessage = mock(LogMessage.class); private final LogActor _logActor = mock(LogActor.class); private final LogSubject _logSubject = mock(LogSubject.class); + private final ServerTransaction _transaction = mock(ServerTransaction.class); + private final CloseAction _closeAction = mock(CloseAction.class); private TransactionTimeoutHelper _transactionTimeoutHelper; - private RootMessageLogger _rootMessageLogger; + private long _now; - public void testLogIfNecessary() + public void testNotTransactional() throws Exception { - _transactionTimeoutHelper.logIfNecessary(99, 100, _logMessage, ""); - verifyZeroInteractions(_logActor, _logMessage); + when(_transaction.isTransactional()).thenReturn(false); - _transactionTimeoutHelper.logIfNecessary(101, 100, _logMessage, ""); - verify(_logActor).message(_logSubject, _logMessage); + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, 5, 10, 5, 10); + + verifyZeroInteractions(_logActor, _closeAction); + } + + public void testOpenTransactionProducesWarningOnly() throws Exception + { + final long sixtyOneSecondsAgo = _now - SECONDS.toMillis(61); + + configureMockTransaction(sixtyOneSecondsAgo, sixtyOneSecondsAgo); + + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, SECONDS.toMillis(30), 0, 0, 0); + + verify(_logActor).message(same(_logSubject), isLogMessage(OPEN_TXN_LOG_HIERARCHY, "CHN-1007 : Open Transaction : 61,\\d{3} ms")); + verifyZeroInteractions(_closeAction); + } + + public void testOpenTransactionProducesTimeoutActionOnly() throws Exception + { + final long sixtyOneSecondsAgo = _now - SECONDS.toMillis(61); + + configureMockTransaction(sixtyOneSecondsAgo, sixtyOneSecondsAgo); + + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, 0, SECONDS.toMillis(30), 0, 0); + + verify(_closeAction).doTimeoutAction("Open transaction timed out"); + verifyZeroInteractions(_logActor); } - public void testLogIfNecessaryWhenOperationalLoggingDisabled() + public void testOpenTransactionProducesWarningAndTimeoutAction() throws Exception { - //disable the operational logging - when(_rootMessageLogger.isMessageEnabled( - same(_logActor), any(LogSubject.class), any(String.class))) - .thenReturn(false); - - //verify the actor is never asked to log a message - _transactionTimeoutHelper.logIfNecessary(101, 100, _logMessage, ""); - verify(_logActor, never()).message(any(LogMessage.class)); - verify(_logActor, never()).message(any(LogSubject.class), any(LogMessage.class)); + final long sixtyOneSecondsAgo = _now - SECONDS.toMillis(61); + + configureMockTransaction(sixtyOneSecondsAgo, sixtyOneSecondsAgo); + + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, SECONDS.toMillis(15), SECONDS.toMillis(30), 0, 0); + + verify(_logActor).message(same(_logSubject), isLogMessage(OPEN_TXN_LOG_HIERARCHY, "CHN-1007 : Open Transaction : 61,\\d{3} ms")); + verify(_closeAction).doTimeoutAction("Open transaction timed out"); } - public void testIsTimedOut() + public void testIdleTransactionProducesWarningOnly() throws Exception { - assertFalse("Shouldn't have timed out", _transactionTimeoutHelper.isTimedOut(199,200)); - assertTrue("Should have timed out", _transactionTimeoutHelper.isTimedOut(201,200)); + final long sixtyOneSecondsAgo = _now - SECONDS.toMillis(61); + final long thrityOneSecondsAgo = _now - SECONDS.toMillis(31); + + configureMockTransaction(sixtyOneSecondsAgo, thrityOneSecondsAgo); + + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, 0, 0, SECONDS.toMillis(30), 0); + + verify(_logActor).message(same(_logSubject), isLogMessage(IDLE_TXN_LOG_HIERARCHY, "CHN-1008 : Idle Transaction : 31,\\d{3} ms")); + verifyZeroInteractions(_closeAction); } - /** - * If TransactionTimeout is disabled, the timeout will be 0. This test verifies - * that the helper methods respond negatively in this scenario. - */ - public void testTransactionTimeoutDisabled() + public void testIdleTransactionProducesTimeoutActionOnly() throws Exception { - assertFalse("Shouldn't have timed out", _transactionTimeoutHelper.isTimedOut(201,0)); + final long sixtyOneSecondsAgo = _now - SECONDS.toMillis(61); + final long thrityOneSecondsAgo = _now - SECONDS.toMillis(31); + + configureMockTransaction(sixtyOneSecondsAgo, thrityOneSecondsAgo); - _transactionTimeoutHelper.logIfNecessary(99, 0, _logMessage, ""); - verifyZeroInteractions(_logActor, _logMessage); + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, 0, 0, 0, SECONDS.toMillis(30)); + + verify(_closeAction).doTimeoutAction("Idle transaction timed out"); + verifyZeroInteractions(_logActor); + } + + public void testIdleTransactionProducesWarningAndTimeoutAction() throws Exception + { + final long sixtyOneSecondsAgo = _now - SECONDS.toMillis(61); + final long thrityOneSecondsAgo = _now - SECONDS.toMillis(31); + + configureMockTransaction(sixtyOneSecondsAgo, thrityOneSecondsAgo); + + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, 0, 0, SECONDS.toMillis(15), SECONDS.toMillis(30)); + + verify(_logActor).message(same(_logSubject), isLogMessage(IDLE_TXN_LOG_HIERARCHY, "CHN-1008 : Idle Transaction : 31,\\d{3} ms")); + verify(_closeAction).doTimeoutAction("Idle transaction timed out"); + } + + public void testIdleAndOpenWarnings() throws Exception + { + final long sixtyOneSecondsAgo = _now - SECONDS.toMillis(61); + final long thirtyOneSecondsAgo = _now - SECONDS.toMillis(31); + + configureMockTransaction(sixtyOneSecondsAgo, thirtyOneSecondsAgo); + + _transactionTimeoutHelper.checkIdleOrOpenTimes(_transaction, SECONDS.toMillis(60), 0, SECONDS.toMillis(30), 0); + + verify(_logActor).message(same(_logSubject), isLogMessage(IDLE_TXN_LOG_HIERARCHY, "CHN-1008 : Idle Transaction : 31,\\d{3} ms")); + verify(_logActor).message(same(_logSubject), isLogMessage(OPEN_TXN_LOG_HIERARCHY, "CHN-1007 : Open Transaction : 61,\\d{3} ms")); + verifyZeroInteractions(_closeAction); } @Override @@ -88,14 +152,79 @@ public class TransactionTimeoutHelperTest extends QpidTestCase CurrentActor.set(_logActor); - _rootMessageLogger = mock(RootMessageLogger.class); - when(_logActor.getRootMessageLogger()).thenReturn(_rootMessageLogger); + _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject, _closeAction); + _now = System.currentTimeMillis(); + } + + @Override + protected void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + CurrentActor.remove(); + } + } - when(_rootMessageLogger.isMessageEnabled( - same(_logActor), any(LogSubject.class), any(String.class))) - .thenReturn(true); + private void configureMockTransaction(final long startTime, final long updateTime) + { + when(_transaction.isTransactional()).thenReturn(true); + when(_transaction.getTransactionStartTime()).thenReturn(startTime); + when(_transaction.getTransactionUpdateTime()).thenReturn(updateTime); + } - _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject); + private LogMessage isLogMessage(String expectedlogHierarchy, String expectedText) + { + return argThat(new IsLogMessage(expectedlogHierarchy, expectedText)); } + class IsLogMessage extends ArgumentMatcher + { + private final String _expectedLogHierarchy; + private final String _expectedLogMessageMatches; + private String _hierarchyMatchesFailure; + private String _logMessageMatchesFailure; + + public IsLogMessage(String expectedlogHierarchy, String expectedLogMessageMatches) + { + _expectedLogHierarchy = expectedlogHierarchy; + _expectedLogMessageMatches = expectedLogMessageMatches; + } + + public boolean matches(Object arg) + { + LogMessage logMessage = (LogMessage)arg; + + boolean hierarchyMatches = logMessage.getLogHierarchy().equals(_expectedLogHierarchy); + boolean logMessageMatches = logMessage.toString().matches(_expectedLogMessageMatches); + + if (!hierarchyMatches) + { + _hierarchyMatchesFailure = "LogHierarchy does not match. Expected " + _expectedLogHierarchy + " actual " + logMessage.getLogHierarchy(); + } + + if (!logMessageMatches) + { + _logMessageMatchesFailure = "LogMessage does not match. Expected " + _expectedLogMessageMatches + " actual " + logMessage.toString(); + } + + return hierarchyMatches && logMessageMatches; + } + + @Override + public void describeTo(Description description) + { + if (_hierarchyMatchesFailure != null) + { + description.appendText(_hierarchyMatchesFailure); + } + if (_logMessageMatchesFailure != null) + { + description.appendText(_logMessageMatchesFailure); + } + } + } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java b/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java index b3223f16c4..4d6d60906d 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java @@ -22,14 +22,72 @@ package org.apache.qpid.server.ack; import org.apache.qpid.AMQException; +import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.queue.SimpleAMQQueue; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TestableMemoryMessageStore; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; import java.util.List; -public class AcknowledgeTest extends InternalBrokerBaseCase +public class AcknowledgeTest extends QpidTestCase { + private AMQChannel _channel; + private SimpleAMQQueue _queue; + private MessageStore _messageStore; + private String _queueName; + + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _channel = BrokerTestHelper.createChannel(); + VirtualHost virtualHost = _channel.getVirtualHost(); + _queueName = getTestName(); + _queue = BrokerTestHelper.createQueue(_queueName, virtualHost); + _messageStore = virtualHost.getMessageStore(); + Exchange defaultExchange = virtualHost.getExchangeRegistry().getDefaultExchange(); + virtualHost.getBindingFactory().addBinding(_queueName, _queue, defaultExchange, null); + } + + @Override + public void tearDown() throws Exception + { + try + { + if (_channel != null) + { + _channel.getVirtualHost().close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + } + + private AMQChannel getChannel() + { + return _channel; + } + + private InternalTestProtocolSession getSession() + { + return (InternalTestProtocolSession)_channel.getProtocolSession(); + } + + private SimpleAMQQueue getQueue() + { + return _queue; + } public void testTransactionalSingleAck() throws AMQException { @@ -70,7 +128,7 @@ public class AcknowledgeTest extends InternalBrokerBaseCase checkStoreContents(0); //Send required messsages to the queue - publishMessages(getSession(), getChannel(), sendMessageCount); + BrokerTestHelper.publishMessages(getChannel(), sendMessageCount, _queueName, ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString()); if (getChannel().isTransactional()) { @@ -84,7 +142,7 @@ public class AcknowledgeTest extends InternalBrokerBaseCase assertEquals("Channel should have no unacked msgs ", 0, getChannel().getUnacknowledgedMessageMap().size()); //Subscribe to the queue - AMQShortString subscriber = subscribe(getSession(), getChannel(), getQueue()); + AMQShortString subscriber = _channel.subscribeToQueue(null, _queue, true, null, false, true); getQueue().deliverAsync(); @@ -117,4 +175,9 @@ public class AcknowledgeTest extends InternalBrokerBaseCase checkStoreContents(remainingUnackedMessages); } + private void checkStoreContents(int messageCount) + { + assertEquals("Message header count incorrect in the MetaDataMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getMessageCount()); + } + } diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreatorTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreatorTest.java new file mode 100644 index 0000000000..fa1bd966a7 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerConfigurationStoreCreatorTest.java @@ -0,0 +1,144 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration; + +import java.io.File; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.util.FileUtils; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; + +public class BrokerConfigurationStoreCreatorTest extends QpidTestCase +{ + private File _userStoreLocation; + private BrokerConfigurationStoreCreator _storeCreator; + + public void setUp() throws Exception + { + super.setUp(); + + // check whether QPID_HOME JVM system property is set + if (QPID_HOME == null) + { + // set the properties in order to resolve the defaults store settings + setTestSystemProperty("QPID_HOME", TMP_FOLDER); + } + _storeCreator = new BrokerConfigurationStoreCreator(); + _userStoreLocation = new File(TMP_FOLDER, "_store_" + System.currentTimeMillis() + "_" + getTestName()); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + if (_userStoreLocation != null) + { + FileUtils.delete(_userStoreLocation, true); + } + } + } + + public void testCreateJsonStore() + { + ConfigurationEntryStore store = _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "json", null, null); + assertNotNull("Store was not created", store); + assertTrue("File should exists", _userStoreLocation.exists()); + assertTrue("File size should be greater than 0", _userStoreLocation.length() > 0); + JsonConfigurationEntryStore jsonStore = new JsonConfigurationEntryStore(); + jsonStore.open(_userStoreLocation.getAbsolutePath()); + Set childrenIds = jsonStore.getRootEntry().getChildrenIds(); + assertFalse("Unexpected children: " + childrenIds, childrenIds.isEmpty()); + } + + public void testCreateJsonStoreFromInitialStore() throws Exception + { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + + Map brokerObjectMap = new HashMap(); + UUID brokerId = UUID.randomUUID(); + brokerObjectMap.put(Broker.ID, brokerId); + brokerObjectMap.put("name", "Test"); + + StringWriter sw = new StringWriter(); + objectMapper.writeValue(sw, brokerObjectMap); + + String brokerJson = sw.toString(); + + File _storeFile = TestFileUtils.createTempFile(this, ".json", brokerJson); + + ConfigurationEntryStore store = _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "json", _storeFile.getAbsolutePath(), "json"); + assertNotNull("Store was not created", store); + assertTrue("File should exists", _userStoreLocation.exists()); + assertTrue("File size should be greater than 0", _userStoreLocation.length() > 0); + JsonConfigurationEntryStore jsonStore = new JsonConfigurationEntryStore(); + jsonStore.open(_userStoreLocation.getAbsolutePath()); + ConfigurationEntry entry = jsonStore.getRootEntry(); + assertEquals("Unexpected root id", brokerId, entry.getId()); + Map attributes = entry.getAttributes(); + assertNotNull("Unexpected attributes: " + attributes, attributes); + assertEquals("Unexpected attributes size: " + attributes.size(), 1, attributes.size()); + assertEquals("Unexpected attribute name: " + attributes.get("name"), "Test", attributes.get("name")); + Set childrenIds = entry.getChildrenIds(); + assertTrue("Unexpected children: " + childrenIds, childrenIds.isEmpty()); + } + + public void testCreateDerbyStore() + { + //TODO: Implement DERBY store + try + { + _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "derby", null, null); + fail("Store is not yet supported"); + } + catch(IllegalConfigurationException e) + { + // pass + } + } + + public void testCreateXmlStore() throws Exception + { + try + { + _storeCreator.createStore(_userStoreLocation.getAbsolutePath(), "xml", null, null); + fail("Store is not yet supported"); + } + catch(IllegalConfigurationException e) + { + // pass + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerPropertiesTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerPropertiesTest.java new file mode 100644 index 0000000000..5e9e19ffaf --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/BrokerPropertiesTest.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration; + +import java.util.Locale; + +import org.apache.qpid.test.utils.QpidTestCase; + +public class BrokerPropertiesTest extends QpidTestCase +{ + public void testGetLocaleDefault() + { + Locale locale = BrokerProperties.getLocale(); + assertEquals("Unexpected locale", Locale.US, locale); + } + + public void testGetLocaleSetWithJVMProperty() + { + setTestSystemProperty(BrokerProperties.PROPERTY_LOCALE, "en_GB"); + Locale locale = BrokerProperties.getLocale(); + assertEquals("Unexpected locale", Locale.UK, locale); + } + + public void testGetLocaleSetWithJVMPropertyInUnexpectedFormat() + { + setTestSystemProperty(BrokerProperties.PROPERTY_LOCALE, "penguins_ANTARCTIC_Moubray_Bay"); + Locale locale = BrokerProperties.getLocale(); + assertEquals("Unexpected locale language", "penguins", locale.getLanguage()); + assertEquals("Unexpected locale country", "ANTARCTIC", locale.getCountry()); + assertEquals("Unexpected locale country", "Moubray_Bay", locale.getVariant()); + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java deleted file mode 100644 index 00e5cd1222..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java +++ /dev/null @@ -1,171 +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.configuration; - -import java.util.UUID; - -public class MockConnectionConfig implements ConnectionConfig -{ - - public MockConnectionConfig(UUID _qmfId, ConnectionConfigType _configType, - ConfiguredObject _parent, boolean _durable, - long _createTime, VirtualHostConfig _virtualHost, String _address, Boolean _incoming, - Boolean _systemConnection, Boolean _federationLink, String _authId, String _remoteProcessName, - Integer _remotePID, Integer _remoteParentPID, ConfigStore _configStore, Boolean _shadow) - { - super(); - this._qmfId = _qmfId; - this._configType = _configType; - this._parent = _parent; - this._durable = _durable; - this._createTime = _createTime; - this._virtualHost = _virtualHost; - this._address = _address; - this._incoming = _incoming; - this._systemConnection = _systemConnection; - this._federationLink = _federationLink; - this._authId = _authId; - this._remoteProcessName = _remoteProcessName; - this._remotePID = _remotePID; - this._remoteParentPID = _remoteParentPID; - this._configStore = _configStore; - this._shadow = _shadow; - } - - private UUID _qmfId; - private ConnectionConfigType _configType; - private ConfiguredObject _parent; - private boolean _durable; - private long _createTime; - private VirtualHostConfig _virtualHost; - private String _address; - private Boolean _incoming; - private Boolean _systemConnection; - private Boolean _federationLink; - private String _authId; - private String _remoteProcessName; - private Integer _remotePID; - private Integer _remoteParentPID; - private ConfigStore _configStore; - private Boolean _shadow; - - @Override - public UUID getQMFId() - { - return _qmfId; - } - - @Override - public ConnectionConfigType getConfigType() - { - return _configType; - } - - @Override - public ConfiguredObject getParent() - { - return _parent; - } - - @Override - public boolean isDurable() - { - return _durable; - } - - @Override - public long getCreateTime() - { - return _createTime; - } - - @Override - public VirtualHostConfig getVirtualHost() - { - return _virtualHost; - } - - @Override - public String getAddress() - { - return _address; - } - - @Override - public Boolean isIncoming() - { - return _incoming; - } - - @Override - public Boolean isSystemConnection() - { - return _systemConnection; - } - - @Override - public Boolean isFederationLink() - { - return _federationLink; - } - - @Override - public String getAuthId() - { - return _authId; - } - - @Override - public String getRemoteProcessName() - { - return _remoteProcessName; - } - - @Override - public Integer getRemotePID() - { - return _remotePID; - } - - @Override - public Integer getRemoteParentPID() - { - return _remoteParentPID; - } - - @Override - public ConfigStore getConfigStore() - { - return _configStore; - } - - @Override - public Boolean isShadow() - { - return _shadow; - } - - @Override - public void mgmtClose() - { - } - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java index 3c5b85cd90..0bb65479ce 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java @@ -20,25 +20,31 @@ */ package org.apache.qpid.server.configuration; +import static org.mockito.Mockito.when; + import junit.framework.TestCase; import org.apache.commons.configuration.CompositeConfiguration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.TestApplicationRegistry; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.util.BrokerTestHelper; public class QueueConfigurationTest extends TestCase { - private VirtualHostConfiguration _emptyConf; private PropertiesConfiguration _env; private VirtualHostConfiguration _fullHostConf; + private Broker _broker; + @Override public void setUp() throws Exception { + super.setUp(); + BrokerTestHelper.setUp(); + _broker = BrokerTestHelper.createBrokerMock(); _env = new PropertiesConfiguration(); - _emptyConf = new VirtualHostConfiguration("test", _env); + _emptyConf = new VirtualHostConfiguration("test", _env, _broker); PropertiesConfiguration fullEnv = new PropertiesConfiguration(); fullEnv.setProperty("queues.maximumMessageAge", 1); @@ -49,35 +55,41 @@ public class QueueConfigurationTest extends TestCase fullEnv.setProperty("queues.deadLetterQueues", true); fullEnv.setProperty("queues.maximumDeliveryCount", 5); - _fullHostConf = new VirtualHostConfiguration("test", fullEnv); + _fullHostConf = new VirtualHostConfiguration("test", fullEnv, _broker); } + @Override + public void tearDown() throws Exception + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + public void testMaxDeliveryCount() throws Exception { - try - { - ApplicationRegistry registry = new TestApplicationRegistry(new ServerConfiguration(_env)); - ApplicationRegistry.initialise(registry); - - // Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertEquals("Unexpected default server configuration for max delivery count ", 0, qConf.getMaxDeliveryCount()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("maximumDeliveryCount", 7); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals("Unexpected host configuration for max delivery count", 7, qConf.getMaxDeliveryCount()); - - // Check inherited value - qConf = new QueueConfiguration("test", _fullHostConf); - assertEquals("Unexpected queue configuration for max delivery count", 5, qConf.getMaxDeliveryCount()); - - } - finally - { - ApplicationRegistry.remove(); - } + // broker MAXIMUM_DELIVERY_ATTEMPTS attribute is not set + when(_broker.getAttribute(Broker.MAXIMUM_DELIVERY_ATTEMPTS)).thenReturn(null); + + // Check default value + QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); + assertEquals("Unexpected default server configuration for max delivery count ", 0, qConf.getMaxDeliveryCount()); + + // set broker MAXIMUM_DELIVERY_ATTEMPTS attribute to 2 + when(_broker.getAttribute(Broker.MAXIMUM_DELIVERY_ATTEMPTS)).thenReturn(2); + + // Check that queue inherits the MAXIMUM_DELIVERY_ATTEMPTS value from broker + qConf = new QueueConfiguration("test", _emptyConf); + assertEquals("Unexpected default server configuration for max delivery count ", 2, qConf.getMaxDeliveryCount()); + + // Check explicit value + VirtualHostConfiguration vhostConfig = overrideConfiguration("maximumDeliveryCount", 7); + qConf = new QueueConfiguration("test", vhostConfig); + assertEquals("Unexpected host configuration for max delivery count", 7, qConf.getMaxDeliveryCount()); + + // Check inherited value + qConf = new QueueConfiguration("test", _fullHostConf); + assertEquals("Unexpected queue configuration for max delivery count", 5, qConf.getMaxDeliveryCount()); } /** @@ -87,28 +99,28 @@ public class QueueConfigurationTest extends TestCase */ public void testIsDeadLetterQueueEnabled() throws Exception { - try - { - ApplicationRegistry registry = new TestApplicationRegistry(new ServerConfiguration(_env)); - ApplicationRegistry.initialise(registry); - - // Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertFalse("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("deadLetterQueues", true); - qConf = new QueueConfiguration("test", vhostConfig); - assertTrue("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); - - // Check inherited value - qConf = new QueueConfiguration("test", _fullHostConf); - assertTrue("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); - } - finally - { - ApplicationRegistry.remove(); - } + // enable dead letter queues broker wide + when(_broker.getAttribute(Broker.DEAD_LETTER_QUEUE_ENABLED)).thenReturn(true); + + // Check that queue inherits the broker setting + QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); + assertTrue("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); + + // broker DEAD_LETTER_QUEUE_ENABLED is not set + when(_broker.getAttribute(Broker.DEAD_LETTER_QUEUE_ENABLED)).thenReturn(null); + + // Check that queue dead letter queue is not enabled + qConf = new QueueConfiguration("test", _emptyConf); + assertFalse("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); + + // Check explicit value + VirtualHostConfiguration vhostConfig = overrideConfiguration("deadLetterQueues", true); + qConf = new QueueConfiguration("test", vhostConfig); + assertTrue("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); + + // Check inherited value + qConf = new QueueConfiguration("test", _fullHostConf); + assertTrue("Unexpected queue configuration for dead letter enabled attribute", qConf.isDeadLetterQueueEnabled()); } public void testGetMaximumMessageAge() throws ConfigurationException @@ -178,27 +190,28 @@ public class QueueConfigurationTest extends TestCase public void testGetMinimumAlertRepeatGap() throws Exception { - try - { - ApplicationRegistry registry = new TestApplicationRegistry(new ServerConfiguration(_env)); - ApplicationRegistry.initialise(registry); - // Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertEquals(ServerConfiguration.DEFAULT_MINIMUM_ALERT_REPEAT_GAP, qConf.getMinimumAlertRepeatGap()); - - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("minimumAlertRepeatGap", 2); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals(2, qConf.getMinimumAlertRepeatGap()); - - // Check inherited value - qConf = new QueueConfiguration("test", _fullHostConf); - assertEquals(1, qConf.getMinimumAlertRepeatGap()); - } - finally - { - ApplicationRegistry.remove(); - } + // set broker attribute ALERT_REPEAT_GAP to 10 + when(_broker.getAttribute(Broker.ALERT_REPEAT_GAP)).thenReturn(10); + + // check that broker level setting is available on queue configuration + QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); + assertEquals(10, qConf.getMinimumAlertRepeatGap()); + + // remove configuration for ALERT_REPEAT_GAP on broker level + when(_broker.getAttribute(Broker.ALERT_REPEAT_GAP)).thenReturn(null); + + // Check default value + qConf = new QueueConfiguration("test", _emptyConf); + assertEquals(0, qConf.getMinimumAlertRepeatGap()); + + // Check explicit value + VirtualHostConfiguration vhostConfig = overrideConfiguration("minimumAlertRepeatGap", 2); + qConf = new QueueConfiguration("test", vhostConfig); + assertEquals(2, qConf.getMinimumAlertRepeatGap()); + + // Check inherited value + qConf = new QueueConfiguration("test", _fullHostConf); + assertEquals(1, qConf.getMinimumAlertRepeatGap()); } public void testSortQueueConfiguration() throws ConfigurationException @@ -235,6 +248,6 @@ public class QueueConfigurationTest extends TestCase config.addConfiguration(_fullHostConf.getConfig()); config.addConfiguration(queueConfig); - return new VirtualHostConfiguration("test", config); + return new VirtualHostConfiguration("test", config, _broker); } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java deleted file mode 100644 index 660ff5e7d4..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java +++ /dev/null @@ -1,1766 +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.configuration; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AmqpProtocolVersion; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; -import org.apache.qpid.server.util.TestApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.test.utils.QpidTestCase; - -import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.util.Locale; - -import javax.net.ssl.KeyManagerFactory; - -public class ServerConfigurationTest extends QpidTestCase -{ - private XMLConfiguration _config = new XMLConfiguration(); - private ServerConfiguration _serverConfig = null; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - _serverConfig = new ServerConfiguration(_config); - ApplicationRegistry.initialise(new TestApplicationRegistry(_serverConfig)); - } - - @Override - protected void tearDown() throws Exception - { - super.tearDown(); - ApplicationRegistry.remove(); - } - - public void testSetJMXPortRegistryServer() throws ConfigurationException - { - _serverConfig.initialise(); - _serverConfig.setJMXPortRegistryServer(23); - assertEquals(23, _serverConfig.getJMXPortRegistryServer()); - } - - public void testGetJMXPortRegistryServer() throws ConfigurationException - { - _config.setProperty(ServerConfiguration.MGMT_JMXPORT_REGISTRYSERVER, 42); - _serverConfig.initialise(); - assertEquals(42, _serverConfig.getJMXPortRegistryServer()); - } - - public void testDefaultJMXPortRegistryServer() throws ConfigurationException - { - _serverConfig.initialise(); - assertEquals(8999, _serverConfig.getJMXPortRegistryServer()); - } - - public void testSetJMXPortConnectorServer() throws ConfigurationException - { - ServerConfiguration serverConfig = new ServerConfiguration(_config); - serverConfig.setJMXPortConnectorServer(67); - assertEquals(67, serverConfig.getJMXConnectorServerPort()); - } - - public void testGetJMXPortConnectorServer() throws ConfigurationException - { - _config.setProperty(ServerConfiguration.MGMT_JMXPORT_CONNECTORSERVER, 67); - ServerConfiguration serverConfig = new ServerConfiguration(_config); - assertEquals(67, serverConfig.getJMXConnectorServerPort()); - } - - public void testDefaultJMXPortConnectorServer() throws ConfigurationException - { - ServerConfiguration serverConfig = new ServerConfiguration(_config); - assertEquals(ServerConfiguration.DEFAULT_JMXPORT_REGISTRYSERVER + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET, - serverConfig.getJMXConnectorServerPort()); - } - - public void testGetPlatformMbeanserver() throws ConfigurationException - { - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getPlatformMbeanserver()); - - // Check value we set - _config.setProperty("management.platform-mbeanserver", false); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getPlatformMbeanserver()); - } - - public void testGetPluginDirectory() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(null, _serverConfig.getPluginDirectory()); - - // Check value we set - _config.setProperty("plugin-directory", "/path/to/plugins"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("/path/to/plugins", _serverConfig.getPluginDirectory()); - } - - public void testGetCacheDirectory() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(null, _serverConfig.getCacheDirectory()); - - // Check value we set - _config.setProperty("cache-directory", "/path/to/cache"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("/path/to/cache", _serverConfig.getCacheDirectory()); - } - - public void testGetFrameSize() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(65536, _serverConfig.getFrameSize()); - - // Check value we set - _config.setProperty("advanced.framesize", "23"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(23, _serverConfig.getFrameSize()); - } - - public void testGetStatusEnabled() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(ServerConfiguration.DEFAULT_STATUS_UPDATES.equalsIgnoreCase("on"), - _serverConfig.getStatusUpdatesEnabled()); - - // Check disabling we set - _config.setProperty(ServerConfiguration.STATUS_UPDATES, "off"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getStatusUpdatesEnabled()); - - // Check invalid values don't cause error but result in disabled - _config.setProperty(ServerConfiguration.STATUS_UPDATES, "Yes Please"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getStatusUpdatesEnabled()); - - } - public void testGetSynchedClocks() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getSynchedClocks()); - - // Check value we set - _config.setProperty("advanced.synced-clocks", true); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getSynchedClocks()); - } - - public void testGetLocale() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - - // The Default is what ever the VMs default is - Locale defaultLocale = Locale.getDefault(); - - assertEquals(defaultLocale, _serverConfig.getLocale()); - - - //Test Language only - Locale update = new Locale("es"); - _config.setProperty(ServerConfiguration.ADVANCED_LOCALE, "es"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(update, _serverConfig.getLocale()); - - //Test Language and Country - update = new Locale("es","ES"); - _config.setProperty(ServerConfiguration.ADVANCED_LOCALE, "es_ES"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(update, _serverConfig.getLocale()); - - //Test Language and Country and Variant - update = new Locale("es","ES", "Traditional_WIN"); - _config.setProperty(ServerConfiguration.ADVANCED_LOCALE, "es_ES_Traditional_WIN"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(update, _serverConfig.getLocale()); - } - - - public void testGetMsgAuth() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getMsgAuth()); - - // Check value we set - _config.setProperty("security.msg-auth", true); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getMsgAuth()); - } - - public void testGetManagementKeyStorePath() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(null, _serverConfig.getManagementKeyStorePath()); - - // Check value we set - _config.setProperty("management.ssl.keyStorePath", "a"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("a", _serverConfig.getManagementKeyStorePath()); - } - - public void testGetManagementSSLEnabled() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getManagementSSLEnabled()); - - // Check value we set - _config.setProperty("management.ssl.enabled", true); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getManagementSSLEnabled()); - } - - public void testGetManagementKeystorePassword() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(null, _serverConfig.getManagementKeyStorePassword()); - - // Check value we set - _config.setProperty("management.ssl.keyStorePassword", "a"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("a", _serverConfig.getManagementKeyStorePassword()); - } - - public void testGetQueueAutoRegister() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getQueueAutoRegister()); - - // Check value we set - _config.setProperty("queue.auto_register", false); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getQueueAutoRegister()); - } - - public void testGetJMXManagementEnabled() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getJMXManagementEnabled()); - - // Check value we set - _config.setProperty("management.enabled", false); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getJMXManagementEnabled()); - } - - public void testGetManagementRightsInferAllAccess() throws Exception - { - _serverConfig.initialise(); - - //check default - assertTrue("default should be true", _serverConfig.getManagementRightsInferAllAccess()); - - //update it - _config.setProperty("management.managementRightsInferAllAccess", "false"); - assertFalse("New value should be false", _serverConfig.getManagementRightsInferAllAccess()); - } - - public void testGetHeartBeatDelay() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(5, _serverConfig.getHeartBeatDelay()); - - // Check value we set - _config.setProperty("heartbeat.delay", 23); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(23, _serverConfig.getHeartBeatDelay()); - } - - public void testGetHeartBeatTimeout() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(2.0, _serverConfig.getHeartBeatTimeout()); - - // Check value we set - _config.setProperty("heartbeat.timeoutFactor", 2.3); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(2.3, _serverConfig.getHeartBeatTimeout()); - } - - public void testGetMaximumMessageAge() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(0, _serverConfig.getMaximumMessageAge()); - - // Check value we set - _config.setProperty("maximumMessageAge", 10L); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(10, _serverConfig.getMaximumMessageAge()); - } - - public void testGetMaximumMessageCount() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(0, _serverConfig.getMaximumMessageCount()); - - // Check value we set - _config.setProperty("maximumMessageCount", 10L); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(10, _serverConfig.getMaximumMessageCount()); - } - - public void testGetMaximumQueueDepth() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(0, _serverConfig.getMaximumQueueDepth()); - - // Check value we set - _config.setProperty("maximumQueueDepth", 10L); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(10, _serverConfig.getMaximumQueueDepth()); - } - - public void testGetMaximumMessageSize() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(0, _serverConfig.getMaximumMessageSize()); - - // Check value we set - _config.setProperty("maximumMessageSize", 10L); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(10, _serverConfig.getMaximumMessageSize()); - } - - public void testGetMinimumAlertRepeatGap() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(30000l, _serverConfig.getMinimumAlertRepeatGap()); - - // Check value we set - _config.setProperty("minimumAlertRepeatGap", 10L); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(10, _serverConfig.getMinimumAlertRepeatGap()); - } - - public void testGetProcessors() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(4, _serverConfig.getConnectorProcessors()); - - // Check value we set - _config.setProperty("connector.processors", 10); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(10, _serverConfig.getConnectorProcessors()); - } - - public void testGetPorts() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertNotNull(_serverConfig.getPorts()); - assertEquals(1, _serverConfig.getPorts().size()); - assertEquals(5672, _serverConfig.getPorts().get(0)); - - - // Check value we set - _config.setProperty("connector.port", "10"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertNotNull(_serverConfig.getPorts()); - assertEquals(1, _serverConfig.getPorts().size()); - assertEquals("10", _serverConfig.getPorts().get(0)); - } - - public void testGetBind() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(WILDCARD_ADDRESS, _serverConfig.getBind()); - - // Check value we set - _config.setProperty("connector.bind", "a"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("a", _serverConfig.getBind()); - } - - public void testGetReceiveBufferSize() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(ServerConfiguration.DEFAULT_BUFFER_SIZE, _serverConfig.getReceiveBufferSize()); - - // Check value we set - _config.setProperty("connector.socketReceiveBuffer", "23"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(23, _serverConfig.getReceiveBufferSize()); - } - - public void testGetWriteBufferSize() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(ServerConfiguration.DEFAULT_BUFFER_SIZE, _serverConfig.getWriteBufferSize()); - - // Check value we set - _config.setProperty("connector.socketWriteBuffer", "23"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(23, _serverConfig.getWriteBufferSize()); - } - - public void testGetTcpNoDelay() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getTcpNoDelay()); - - // Check value we set - _config.setProperty("connector.tcpNoDelay", false); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getTcpNoDelay()); - } - - public void testGetEnableSSL() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getEnableSSL()); - - // Check value we set - _config.setProperty("connector.ssl.enabled", true); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getEnableSSL()); - } - - public void testGetSSLOnly() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(false, _serverConfig.getSSLOnly()); - - // Check value we set - _config.setProperty("connector.ssl.sslOnly", true); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getSSLOnly()); - } - - public void testGetSSLPorts() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertNotNull(_serverConfig.getSSLPorts()); - assertEquals(1, _serverConfig.getSSLPorts().size()); - assertEquals(ServerConfiguration.DEFAULT_SSL_PORT, _serverConfig.getSSLPorts().get(0)); - - - // Check value we set - _config.setProperty("connector.ssl.port", "10"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertNotNull(_serverConfig.getSSLPorts()); - assertEquals(1, _serverConfig.getSSLPorts().size()); - assertEquals("10", _serverConfig.getSSLPorts().get(0)); - } - - public void testGetConnectorKeystorePath() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertNull(_serverConfig.getConnectorKeyStorePath()); - - // Check value we set - _config.setProperty("connector.ssl.keyStorePath", "a"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("a", _serverConfig.getConnectorKeyStorePath()); - - // Ensure we continue to support the old name keystorePath - _config.clearProperty("connector.ssl.keyStorePath"); - _config.setProperty("connector.ssl.keystorePath", "b"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("b", _serverConfig.getConnectorKeyStorePath()); - } - - public void testGetConnectorKeystorePassword() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertNull(_serverConfig.getConnectorKeyStorePassword()); - - // Check value we set - _config.setProperty("connector.ssl.keyStorePassword", "a"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("a", _serverConfig.getConnectorKeyStorePassword()); - - // Ensure we continue to support the old name keystorePassword - _config.clearProperty("connector.ssl.keyStorePassword"); - _config.setProperty("connector.ssl.keystorePassword", "b"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("b", _serverConfig.getConnectorKeyStorePassword()); - } - - public void testConnectorGetKeyManagerAlgorithm() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(KeyManagerFactory.getDefaultAlgorithm(), _serverConfig.getConnectorKeyManagerFactoryAlgorithm()); - - // Check value we set - _config.setProperty("connector.ssl.keyManagerFactoryAlgorithm", "a"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("a", _serverConfig.getConnectorKeyManagerFactoryAlgorithm()); - - // Ensure we continue to support the old name certType - _config.clearProperty("connector.ssl.keyManagerFactoryAlgorithm"); - _config.setProperty("connector.ssl.certType", "b"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("b", _serverConfig.getConnectorKeyManagerFactoryAlgorithm()); - } - - public void testGetHousekeepingCheckPeriod() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(30000, _serverConfig.getHousekeepingCheckPeriod()); - - // Check value we set - _config.setProperty("housekeeping.checkPeriod", 23L); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - _serverConfig.setHousekeepingCheckPeriod(42L); - assertEquals(42, _serverConfig.getHousekeepingCheckPeriod()); - } - - public void testSingleConfiguration() throws IOException, ConfigurationException - { - File fileA = File.createTempFile(getClass().getName(), null); - fileA.deleteOnExit(); - FileWriter out = new FileWriter(fileA); - out.write("23424235"); - out.close(); - ServerConfiguration conf = new ServerConfiguration(fileA); - conf.initialise(); - assertEquals("4235", conf.getSSLPorts().get(0)); - } - - public void testCombinedConfiguration() throws IOException, ConfigurationException - { - File mainFile = File.createTempFile(getClass().getName(), null); - File fileA = File.createTempFile(getClass().getName(), null); - File fileB = File.createTempFile(getClass().getName(), null); - - mainFile.deleteOnExit(); - fileA.deleteOnExit(); - fileB.deleteOnExit(); - - FileWriter out = new FileWriter(mainFile); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.close(); - - out = new FileWriter(fileA); - out.write("23424235"); - out.close(); - - out = new FileWriter(fileB); - out.write("2345"); - out.close(); - - ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - config.initialise(); - assertEquals("4235", config.getSSLPorts().get(0)); // From first file, not - // overriden by second - assertNotNull(config.getPorts()); - assertEquals(1, config.getPorts().size()); - assertEquals("2342", config.getPorts().get(0)); // From the first file, not - // present in the second - } - - public void testVariableInterpolation() throws Exception - { - File mainFile = File.createTempFile(getClass().getName(), null); - - mainFile.deleteOnExit(); - - FileWriter out = new FileWriter(mainFile); - out.write("\n"); - out.write("\tfoo\n"); - out.write("\t${work}\n"); - out.write("\n"); - out.close(); - - ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - config.initialise(); - assertEquals("Did not get correct interpolated value", - "foo", config.getManagementKeyStorePath()); - } - - private void writeConfigFile(File mainFile, boolean allow) throws IOException { - writeConfigFile(mainFile, allow, true, null, "test"); - } - - private void writeConfigFile(File mainFile, boolean allow, boolean includeVhosts, File vhostsFile, String name) throws IOException { - FileWriter out = new FileWriter(mainFile); - out.write("\n"); - out.write("\tfalse\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\torg.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\t\tpasswordFile\n"); - out.write("\t\t\t\t\t\t/dev/null\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t"); - out.write("\t\t\n"); - out.write("\t\n"); - if (includeVhosts) - { - out.write("\t\n"); - out.write("\t\ttest\n"); - out.write("\t\t\n"); - out.write(String.format("\t\t\t%s\n", name)); - out.write(String.format("\t\t<%s> \n", name)); - out.write("\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\ttopic\n"); - out.write(String.format("\t\t\t\t\t%s.topic\n", name)); - out.write("\t\t\t\t\ttrue\n"); - out.write("\t\t\t\t\n"); - out.write("\t\tt\n"); - out.write(String.format("\t\t \n", name)); - out.write("\t\t\n"); - out.write("\t\n"); - } - if (vhostsFile != null) - { - out.write("\t"+vhostsFile.getAbsolutePath()+"\n"); - } - out.write("\n"); - out.close(); - } - - private void writeTestFishConfigFile(File mainFile) throws IOException { - FileWriter out = new FileWriter(mainFile); - out.write("\n"); - out.write("\tfalse\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\torg.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\t\tpasswordFile\n"); - out.write("\t\t\t\t\t\t/dev/null\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\ttest\n"); - out.write("\t\t \n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\ttopic\n"); - out.write("\t\t\t\t\ttest.topic\n"); - out.write("\t\t\t\t\ttrue\n"); - out.write("\t\t\t\t\n"); - out.write("\t\tt\n"); - out.write("\t\t \n"); - out.write("\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\tfish\n"); - out.write("\t\t \n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\ttopic\n"); - out.write("\t\t\t\t\tfish.topic\n"); - out.write("\t\t\t\t\tfalse\n"); - out.write("\t\t\t\t\n"); - out.write("\t\tt\n"); - out.write("\t\t \n"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\n"); - out.close(); - } - - private void writeVirtualHostsFile(File vhostsFile, String name) throws IOException { - FileWriter out = new FileWriter(vhostsFile); - out.write("\n"); - out.write(String.format("\t\t%s\n", name)); - out.write("\t\n"); - out.write(String.format("\t\t%s\n", name)); - out.write(String.format("\t\t<%s>\n", name)); - out.write("\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\ttopic\n"); - out.write("\t\t\t\t\ttest.topic\n"); - out.write("\t\t\t\t\ttrue\n"); - out.write("\t\t\t\t\n"); - out.write("\t\tt\n"); - out.write(String.format("\t\t\n", name)); - out.write("\t\n"); - out.write("\n"); - out.close(); - } - - private void writeMultiVirtualHostsFile(File vhostsFile) throws IOException { - FileWriter out = new FileWriter(vhostsFile); - out.write("\n"); - out.write("\t\n"); - out.write("\t\ttopic\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\ttopic\n"); - out.write("\t\t\t\t\ttest.topic\n"); - out.write("\t\t\t\t\ttrue\n"); - out.write("\t\t\t\t\n"); - out.write("\t\tt\n"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\t\n"); - out.write("\t\tfanout\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\tfanout\n"); - out.write("\t\t\t\t\ttest.fanout\n"); - out.write("\t\t\t\t\ttrue\n"); - out.write("\t\t\t\t\n"); - out.write("\t\tt\n"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\n"); - out.close(); - } - - private void writeMultipleVhostsConfigFile(File mainFile, File[] vhostsFileArray) throws IOException { - FileWriter out = new FileWriter(mainFile); - out.write("\n"); - out.write("\tfalse\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\torg.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\t\tpasswordFile\n"); - out.write("\t\t\t\t\t\t/dev/null\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t"); - out.write("\t\t\n"); - out.write("\t\n"); - for (File vhostsFile : vhostsFileArray) - { - out.write("\t"+vhostsFile.getAbsolutePath()+"\n"); - } - out.write("\n"); - out.close(); - } - - private void writeCombinedConfigFile(File mainFile, File fileA, File fileB) throws Exception - { - FileWriter out = new FileWriter(mainFile); - out.write(""); - out.write(""); - out.write(""); - out.write(""); - out.close(); - } - - /** - * Test that configuration loads correctly when virtual hosts are specified in the main - * configuration file only. - *

- * Test for QPID-2361 - */ - public void testInternalVirtualhostConfigFile() throws Exception - { - // Write out config - File mainFile = File.createTempFile(getClass().getName(), "config"); - mainFile.deleteOnExit(); - writeConfigFile(mainFile, false, true, null, "test"); - - // Load config - ApplicationRegistry.remove(); - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - - // Test config - VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry(); - String defaultVirtualHost = reg.getConfiguration().getDefaultVirtualHost(); - VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); - Exchange exchange = virtualHost.getExchangeRegistry().getExchange(new AMQShortString("test.topic")); - - assertEquals("Incorrect default host", "test", defaultVirtualHost); - assertEquals("Incorrect virtualhost count", 1, virtualHostRegistry.getVirtualHosts().size()); - assertEquals("Incorrect virtualhost name", "test", virtualHost.getName()); - assertEquals("Incorrect exchange type", "topic", exchange.getType().getName().toString()); - } - - /** - * Test that configuration loads correctly when virtual hosts are specified in an external - * configuration file only. - *

- * Test for QPID-2361 - */ - public void testExternalVirtualhostXMLFile() throws Exception - { - // Write out config - File mainFile = File.createTempFile(getClass().getName(), "config"); - mainFile.deleteOnExit(); - File vhostsFile = File.createTempFile(getClass().getName(), "vhosts"); - vhostsFile.deleteOnExit(); - writeConfigFile(mainFile, false, false, vhostsFile, null); - writeVirtualHostsFile(vhostsFile, "test"); - - // Load config - ApplicationRegistry.remove(); - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - - // Test config - VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry(); - String defaultVirtualHost = reg.getConfiguration().getDefaultVirtualHost(); - VirtualHost virtualHost = virtualHostRegistry.getVirtualHost("test"); - Exchange exchange = virtualHost.getExchangeRegistry().getExchange(new AMQShortString("test.topic")); - - assertEquals("Incorrect default host", "test", defaultVirtualHost); - assertEquals("Incorrect virtualhost count", 1, virtualHostRegistry.getVirtualHosts().size()); - assertEquals("Incorrect virtualhost name", "test", virtualHost.getName()); - assertEquals("Incorrect exchange type", "topic", exchange.getType().getName().toString()); - } - - /** - * Test that configuration loads correctly when virtual hosts are specified in an external - * configuration file only, with two vhosts that have different properties. - *

- * Test for QPID-2361 - */ - public void testExternalMultiVirtualhostXMLFile() throws Exception - { - // Write out vhosts - File vhostsFile = File.createTempFile(getClass().getName(), "vhosts-multi"); - vhostsFile.deleteOnExit(); - writeMultiVirtualHostsFile(vhostsFile); - - // Write out config - File mainFile = File.createTempFile(getClass().getName(), "config"); - mainFile.deleteOnExit(); - writeConfigFile(mainFile, false, false, vhostsFile, null); - - // Load config - ApplicationRegistry.remove(); - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - - // Test config - VirtualHostRegistry virtualHostRegistry = reg.getVirtualHostRegistry(); - - assertEquals("Incorrect virtualhost count", 2, virtualHostRegistry.getVirtualHosts().size()); - - // test topic host - VirtualHost topicVirtualHost = virtualHostRegistry.getVirtualHost("topic"); - Exchange topicExchange = topicVirtualHost.getExchangeRegistry().getExchange(new AMQShortString("test.topic")); - - assertEquals("Incorrect topic virtualhost name", "topic", topicVirtualHost.getName()); - assertEquals("Incorrect topic exchange type", "topic", topicExchange.getType().getName().toString()); - - // Test fanout host - VirtualHost fanoutVirtualHost = virtualHostRegistry.getVirtualHost("fanout"); - Exchange fanoutExchange = fanoutVirtualHost.getExchangeRegistry().getExchange(new AMQShortString("test.fanout")); - - assertEquals("Incorrect fanout virtualhost name", "fanout", fanoutVirtualHost.getName()); - assertEquals("Incorrect fanout exchange type", "fanout", fanoutExchange.getType().getName().toString()); - } - - /** - * Test that configuration does not load when virtual hosts are specified in both the main - * configuration file and an external file. Should throw a {@link ConfigurationException}. - *

- * Test for QPID-2361 - */ - public void testInternalAndExternalVirtualhostXMLFile() throws Exception - { - // Write out vhosts - File vhostsFile = File.createTempFile(getClass().getName(), "vhosts"); - vhostsFile.deleteOnExit(); - writeVirtualHostsFile(vhostsFile, "test"); - - // Write out config - File mainFile = File.createTempFile(getClass().getName(), "config"); - mainFile.deleteOnExit(); - writeConfigFile(mainFile, false, true, vhostsFile, "test"); - - // Load config - try - { - ApplicationRegistry.remove(); - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - fail("Different virtualhost XML configurations not allowed"); - } - catch (ConfigurationException ce) - { - assertEquals("Incorrect error message", "Only one of external or embedded virtualhosts configuration allowed.", ce.getMessage()); - } - } - - /** - * Test that configuration does not load when virtual hosts are specified in multiple external - * files. Should throw a {@link ConfigurationException}. - *

- * Test for QPID-2361 - */ - public void testMultipleInternalVirtualhostXMLFile() throws Exception - { - // Write out vhosts - File vhostsFileOne = File.createTempFile(getClass().getName(), "vhosts-one"); - vhostsFileOne.deleteOnExit(); - writeVirtualHostsFile(vhostsFileOne, "one"); - File vhostsFileTwo = File.createTempFile(getClass().getName(), "vhosts-two"); - vhostsFileTwo.deleteOnExit(); - writeVirtualHostsFile(vhostsFileTwo, "two"); - - // Write out config - File mainFile = File.createTempFile(getClass().getName(), "config"); - mainFile.deleteOnExit(); - writeMultipleVhostsConfigFile(mainFile, new File[] { vhostsFileOne, vhostsFileTwo }); - - // Load config - try - { - ApplicationRegistry.remove(); - ApplicationRegistry reg = new ConfigurationFileApplicationRegistry(mainFile); - ApplicationRegistry.initialise(reg); - fail("Multiple virtualhost XML configurations not allowed"); - } - catch (ConfigurationException ce) - { - assertEquals("Incorrect error message", - "Only one external virtualhosts configuration file allowed, multiple filenames found.", - ce.getMessage()); - } - } - - /** - * Test that configuration loads correctly when virtual hosts are specified in an external - * configuration file in the first of two configurations and embedded in the second. This - * will throe a {@link ConfigurationException} since the configurations have different - * types. - *

- * Test for QPID-2361 - */ - public void testCombinedDifferentVirtualhostConfig() throws Exception - { - // Write out vhosts config - File vhostsFile = File.createTempFile(getClass().getName(), "vhosts"); - vhostsFile.deleteOnExit(); - writeVirtualHostsFile(vhostsFile, "external"); - - // Write out combined config file - File mainFile = File.createTempFile(getClass().getName(), "main"); - File fileA = File.createTempFile(getClass().getName(), "a"); - File fileB = File.createTempFile(getClass().getName(), "b"); - mainFile.deleteOnExit(); - fileA.deleteOnExit(); - fileB.deleteOnExit(); - writeCombinedConfigFile(mainFile, fileA, fileB); - writeConfigFile(fileA, false, false, vhostsFile, null); - writeConfigFile(fileB, false); - - // Load config - try - { - ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - config.initialise(); - fail("Different virtualhost XML configurations not allowed"); - } - catch (ConfigurationException ce) - { - assertEquals("Incorrect error message", "Only one of external or embedded virtualhosts configuration allowed.", ce.getMessage()); - } - } - - /** - * Test that configuration loads correctly when virtual hosts are specified two overriding configurations - * each with an embedded virtualhost section. The first configuration section should be used. - *

- * Test for QPID-2361 - */ - public void testCombinedConfigEmbeddedVirtualhost() throws Exception - { - // Write out combined config file - File mainFile = File.createTempFile(getClass().getName(), "main"); - File fileA = File.createTempFile(getClass().getName(), "a"); - File fileB = File.createTempFile(getClass().getName(), "b"); - mainFile.deleteOnExit(); - fileA.deleteOnExit(); - fileB.deleteOnExit(); - writeCombinedConfigFile(mainFile, fileA, fileB); - writeConfigFile(fileA, false, true, null, "a"); - writeConfigFile(fileB, false, true, null, "b"); - - // Load config - ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - config.initialise(); - - // Test config - VirtualHostConfiguration virtualHost = config.getVirtualHostConfig("a"); - - assertEquals("Incorrect virtualhost count", 1, config.getVirtualHosts().length); - assertEquals("Incorrect virtualhost name", "a", virtualHost.getName()); - } - - /** - * Test that configuration loads correctly when virtual hosts are specified two overriding configurations - * each with an external virtualhost XML file. The first configuration file should be used. - *

- * Test for QPID-2361 - */ - public void testCombinedConfigExternalVirtualhost() throws Exception - { - // Write out vhosts config - File vhostsOne = File.createTempFile(getClass().getName(), "vhosts-one"); - vhostsOne.deleteOnExit(); - writeVirtualHostsFile(vhostsOne, "one"); - File vhostsTwo = File.createTempFile(getClass().getName(), "vhosts-two"); - vhostsTwo.deleteOnExit(); - writeVirtualHostsFile(vhostsTwo, "two"); - - // Write out combined config file - File mainFile = File.createTempFile(getClass().getName(), "main"); - File fileA = File.createTempFile(getClass().getName(), "a"); - File fileB = File.createTempFile(getClass().getName(), "b"); - mainFile.deleteOnExit(); - fileA.deleteOnExit(); - fileB.deleteOnExit(); - writeCombinedConfigFile(mainFile, fileA, fileB); - writeConfigFile(fileA, false, false, vhostsOne, null); - writeConfigFile(fileB, false, false, vhostsTwo, null); - - // Load config - ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - config.initialise(); - - // Test config - VirtualHostConfiguration virtualHost = config.getVirtualHostConfig("one"); - - assertEquals("Incorrect virtualhost count", 1, config.getVirtualHosts().length); - assertEquals("Incorrect virtualhost name", "one", virtualHost.getName()); - } - - /** - * Test that configuration loads correctly when an overriding virtualhost configuration resets - * a property of an embedded virtualhost section. The overriding configuration property value - * should be used. - *

- * Test for QPID-2361 - */ - public void testCombinedConfigEmbeddedVirtualhostOverride() throws Exception - { - // Write out combined config file - File mainFile = File.createTempFile(getClass().getName(), "main"); - File fileA = File.createTempFile(getClass().getName(), "override"); - File fileB = File.createTempFile(getClass().getName(), "config"); - mainFile.deleteOnExit(); - fileA.deleteOnExit(); - fileB.deleteOnExit(); - writeCombinedConfigFile(mainFile, fileA, fileB); - writeTestFishConfigFile(fileB); - - // Write out overriding virtualhosts section - FileWriter out = new FileWriter(fileA); - out.write("\n"); - out.write("\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\tfalse\n"); - out.write("\t\t\t\t\n"); - out.write("\t\tt\n"); - out.write("\t\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\ttrue\n"); - out.write("\t\t\t\t\n"); - out.write("\t\tt\n"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\n"); - out.write("\n"); - out.close(); - - // Load config - ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - config.initialise(); - - // Test config - VirtualHostConfiguration testHost = config.getVirtualHostConfig("test"); - ExchangeConfiguration testExchange = testHost.getExchangeConfiguration("test.topic"); - VirtualHostConfiguration fishHost = config.getVirtualHostConfig("fish"); - ExchangeConfiguration fishExchange = fishHost.getExchangeConfiguration("fish.topic"); - - assertEquals("Incorrect virtualhost count", 2, config.getVirtualHosts().length); - assertEquals("Incorrect virtualhost name", "test", testHost.getName()); - assertFalse("Incorrect exchange durable property", testExchange.getDurable()); - assertEquals("Incorrect virtualhost name", "fish", fishHost.getName()); - assertTrue("Incorrect exchange durable property", fishExchange.getDurable()); - } - - /** - * Test that configuration loads correctly when the virtualhost configuration is a set of overriding - * configuration files that resets a property of a virtualhost. The opmost overriding configuration - * property value should be used. - *

- * Test for QPID-2361 - */ - public void testCombinedVirtualhostOverride() throws Exception - { - // Write out combined config file - File mainFile = File.createTempFile(getClass().getName(), "main"); - File vhostsFile = File.createTempFile(getClass().getName(), "vhosts"); - File fileA = File.createTempFile(getClass().getName(), "vhosts-override"); - File fileB = File.createTempFile(getClass().getName(), "vhosts-base"); - mainFile.deleteOnExit(); - vhostsFile.deleteOnExit(); - fileA.deleteOnExit(); - fileB.deleteOnExit(); - writeConfigFile(mainFile, true, false, vhostsFile, null); - writeCombinedConfigFile(vhostsFile, fileA, fileB); - - // Write out overriding virtualhosts sections - FileWriter out = new FileWriter(fileA); - out.write("\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\tfalse\n"); - out.write("\t\t\t\t\n"); - out.write("\t\tt\n"); - out.write("\t\t\n"); - out.write("\t\n"); - out.write("\n"); - out.close(); - writeVirtualHostsFile(fileB, "test"); - - // Load config - ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - config.initialise(); - - // Test config - VirtualHostConfiguration testHost = config.getVirtualHostConfig("test"); - ExchangeConfiguration testExchange = testHost.getExchangeConfiguration("test.topic"); - - assertEquals("Incorrect virtualhost count", 1, config.getVirtualHosts().length); - assertEquals("Incorrect virtualhost name", "test", testHost.getName()); - assertFalse("Incorrect exchange durable property", testExchange.getDurable()); - } - - /** - * Test that configuration loads correctly when the virtualhost configuration is a set of overriding - * configuration files that define multiple virtualhosts, one per file. Only the virtualhosts defined in - * the topmost file should be used. - *

- * Test for QPID-2361 - */ - public void testCombinedMultipleVirtualhosts() throws Exception - { - // Write out combined config file - File mainFile = File.createTempFile(getClass().getName(), "main"); - File vhostsFile = File.createTempFile(getClass().getName(), "vhosts"); - File fileA = File.createTempFile(getClass().getName(), "vhosts-one"); - File fileB = File.createTempFile(getClass().getName(), "vhosts-two"); - mainFile.deleteOnExit(); - vhostsFile.deleteOnExit(); - fileA.deleteOnExit(); - fileB.deleteOnExit(); - writeConfigFile(mainFile, true, false, vhostsFile, null); - writeCombinedConfigFile(vhostsFile, fileA, fileB); - - // Write both virtualhosts definitions - writeVirtualHostsFile(fileA, "test-one"); - writeVirtualHostsFile(fileB, "test-two"); - - // Load config - ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - config.initialise(); - - // Test config - VirtualHostConfiguration oneHost = config.getVirtualHostConfig("test-one"); - - assertEquals("Incorrect virtualhost count", 1, config.getVirtualHosts().length); - assertEquals("Incorrect virtualhost name", "test-one", oneHost.getName()); - } - - /** - * Test that a non-existent virtualhost file throws a {@link ConfigurationException}. - *

- * Test for QPID-2624 - */ - public void testNonExistantVirtualhosts() throws Exception - { - // Write out combined config file - File mainFile = File.createTempFile(getClass().getName(), "main"); - File vhostsFile = new File("doesnotexist"); - mainFile.deleteOnExit(); - writeConfigFile(mainFile, true, false, vhostsFile, null); - - // Load config - try - { - ServerConfiguration config = new ServerConfiguration(mainFile.getAbsoluteFile()); - config.initialise(); - } - catch (ConfigurationException ce) - { - assertEquals("Virtualhosts file does not exist", ce.getMessage()); - } - catch (Exception e) - { - fail("Should throw a ConfigurationException"); - } - } - - /** - * Tests that element disabledFeatures allows features that would - * otherwise be advertised by the broker to be turned off. - */ - public void testDisabledFeatures() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - _serverConfig = new ServerConfiguration(_config); - assertEquals("Unexpected size", 0, _serverConfig.getDisabledFeatures().size()); - - // Check value we set - _config.addProperty("disabledFeatures", "qpid.feature1"); - _config.addProperty("disabledFeatures", "qpid.feature2"); - _serverConfig = new ServerConfiguration(_config); - - assertEquals("Unexpected size",2, _serverConfig.getDisabledFeatures().size()); - assertTrue("Unexpected contents", _serverConfig.getDisabledFeatures().contains("qpid.feature1")); - } - - /** - * Tests that the old element security.jmx.access (that used to be used - * to define JMX access rights) is rejected. - */ - public void testManagementAccessRejected() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - - // Check value we set - _config.setProperty("security.jmx.access(0)", "jmxremote.access"); - _serverConfig = new ServerConfiguration(_config); - - try - { - _serverConfig.initialise(); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - assertEquals("Incorrect error message", - "Validation error : security/jmx/access is no longer a supported element within the configuration xml.", - ce.getMessage()); - } - } - - /** - * Tests that the old element security.jmx.principal-database (that used to define the - * principal database used for JMX authentication) is rejected. - */ - public void testManagementPrincipalDatabaseRejected() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - - // Check value we set - _config.setProperty("security.jmx.principal-database(0)", "mydb"); - _serverConfig = new ServerConfiguration(_config); - - try - { - _serverConfig.initialise(); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - assertEquals("Incorrect error message", - "Validation error : security/jmx/principal-database is no longer a supported element within the configuration xml.", - ce.getMessage()); - } - } - - /** - * Tests that the old element security.principal-databases. ... (that used to define - * principal databases) is rejected. - */ - public void testPrincipalDatabasesRejected() throws ConfigurationException - { - _serverConfig.initialise(); - - // Check value we set - _config.setProperty("security.principal-databases.principal-database.class", "myclass"); - _serverConfig = new ServerConfiguration(_config); - - try - { - _serverConfig.initialise(); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - assertEquals("Incorrect error message", - "Validation error : security/principal-databases is no longer supported within the configuration xml.", - ce.getMessage()); - } - } - - /** - * Tests that the old element housekeeping.expiredMessageCheckPeriod. ... (that was - * replaced by housekeeping.checkPeriod) is rejected. - */ - public void testExpiredMessageCheckPeriodRejected() throws ConfigurationException - { - _serverConfig.initialise(); - - // Check value we set - _config.setProperty("housekeeping.expiredMessageCheckPeriod", 23L); - _serverConfig = new ServerConfiguration(_config); - - try - { - _serverConfig.initialise(); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - assertEquals("Incorrect error message", - "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod.", - ce.getMessage()); - } - } - - public void testMaxDeliveryCountDefault() throws Exception - { - final ServerConfiguration serverConfig = new ServerConfiguration(_config); - assertEquals(0, serverConfig.getMaxDeliveryCount()); - } - - public void testMaxDeliveryCount() throws Exception - { - _config.setProperty("maximumDeliveryCount", 5); - final ServerConfiguration serverConfig = new ServerConfiguration(_config); - assertEquals(5, serverConfig.getMaxDeliveryCount()); - } - - /** - * Test XML configuration file correctly enables dead letter queues - */ - public void testDeadLetterQueueConfigurationFile() throws Exception - { - // Write config - File xml = File.createTempFile(getClass().getName(), "xml"); - xml.deleteOnExit(); - FileWriter config = new FileWriter(xml); - config.write("\n"); - writeSecurity(config); - config.write("true\n"); - config.write("\n"); - config.write("\n"); - config.write("test\n"); - config.write("\n"); - config.write("\n"); - config.write("false\n"); - config.write("\n"); - config.write("biggles\n"); - config.write("\n"); - config.write("true\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("beetle\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("extra\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("r2d2\n"); - config.write("\n"); - config.write("false\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("c3p0\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.write("\n"); - config.close(); - - // Load config - ApplicationRegistry.remove(); - ApplicationRegistry registry = new ConfigurationFileApplicationRegistry(xml); - ApplicationRegistry.initialise(registry); - ServerConfiguration serverConfiguration = ApplicationRegistry.getInstance().getConfiguration(); - - VirtualHostConfiguration test = serverConfiguration.getVirtualHostConfig("test"); - assertNotNull("Host 'test' is not found", test); - VirtualHostConfiguration extra = serverConfiguration.getVirtualHostConfig("extra"); - assertNotNull("Host 'extra' is not found", test); - - QueueConfiguration biggles = test.getQueueConfiguration("biggles"); - QueueConfiguration beetle = test.getQueueConfiguration("beetle"); - QueueConfiguration r2d2 = extra.getQueueConfiguration("r2d2"); - QueueConfiguration c3p0 = extra.getQueueConfiguration("c3p0"); - - // Validate config - assertTrue("Broker DLQ should be configured as enabled", serverConfiguration.isDeadLetterQueueEnabled()); - assertFalse("Test vhost DLQ should be configured as disabled", test.isDeadLetterQueueEnabled()); - assertTrue("Extra vhost DLQ should be enabled, using broker default", extra.isDeadLetterQueueEnabled()); - assertTrue("Biggles queue DLQ should be configured as enabled", biggles.isDeadLetterQueueEnabled()); - assertFalse("Beetle queue DLQ should be disabled, using test vhost default", beetle.isDeadLetterQueueEnabled()); - assertFalse("R2D2 queue DLQ should be configured as disabled", r2d2.isDeadLetterQueueEnabled()); - assertTrue("C3P0 queue DLQ should be enabled, using broker default", c3p0.isDeadLetterQueueEnabled()); - } - - public void testIsAmqp010enabled() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.isAmqp010enabled()); - - // Check value we set - _config.setProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, false); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.isAmqp010enabled()); - } - - public void testIsAmqp091enabled() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.isAmqp091enabled()); - - // Check value we set - _config.setProperty(ServerConfiguration.CONNECTOR_AMQP091ENABLED, false); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.isAmqp091enabled()); - } - - public void testIsAmqp09enabled() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.isAmqp09enabled()); - - // Check value we set - _config.setProperty(ServerConfiguration.CONNECTOR_AMQP09ENABLED, false); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.isAmqp09enabled()); - } - - public void testIsAmqp08enabled() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.isAmqp08enabled()); - - // Check value we set - _config.setProperty(ServerConfiguration.CONNECTOR_AMQP08ENABLED, false); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(false, _serverConfig.isAmqp08enabled()); - } - - public void testPortInclude08() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getPortInclude08().isEmpty()); - - // Check values we set - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_08, "1"); - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_08, "2"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(2, _serverConfig.getPortInclude08().size()); - assertTrue(_serverConfig.getPortInclude08().contains("1")); - assertTrue(_serverConfig.getPortInclude08().contains("2")); - } - - public void testPortInclude09() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getPortInclude09().isEmpty()); - - // Check values we set - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_09, "3"); - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_09, "4"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(2, _serverConfig.getPortInclude09().size()); - assertTrue(_serverConfig.getPortInclude09().contains("3")); - assertTrue(_serverConfig.getPortInclude09().contains("4")); - } - - public void testPortInclude091() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getPortInclude091().isEmpty()); - - // Check values we set - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_091, "5"); - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_091, "6"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(2, _serverConfig.getPortInclude091().size()); - assertTrue(_serverConfig.getPortInclude091().contains("5")); - assertTrue(_serverConfig.getPortInclude091().contains("6")); - } - - public void testPortInclude010() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getPortInclude010().isEmpty()); - - // Check values we set - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, "7"); - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, "8"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(2, _serverConfig.getPortInclude010().size()); - assertTrue(_serverConfig.getPortInclude010().contains("7")); - assertTrue(_serverConfig.getPortInclude010().contains("8")); - } - - public void testPortInclude10() throws ConfigurationException - { - // Check default - _serverConfig.initialise(); - assertEquals(true, _serverConfig.getPortInclude10().isEmpty()); - - // Check values we set - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_10, "9"); - _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_10, "10"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(2, _serverConfig.getPortInclude10().size()); - assertTrue(_serverConfig.getPortInclude10().contains("9")); - assertTrue(_serverConfig.getPortInclude10().contains("10")); - } - - public void testGetDefaultSupportedProtocolReply() throws Exception - { - // Check default - _serverConfig.initialise(); - assertNull("unexpected default value", _serverConfig.getDefaultSupportedProtocolReply()); - - // Check values we set - _config.addProperty(ServerConfiguration.CONNECTOR_AMQP_SUPPORTED_REPLY, "v0_10"); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(AmqpProtocolVersion.v0_10, _serverConfig.getDefaultSupportedProtocolReply()); - } - - public void testDefaultAuthenticationManager() throws Exception - { - // Check default - _serverConfig.initialise(); - assertNull("unexpected default value", _serverConfig.getDefaultAuthenticationManager()); - - // Check values we set - String testAuthManager = "myauthmanager"; - _config.addProperty("security.default-auth-manager", testAuthManager); - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals(testAuthManager, _serverConfig.getDefaultAuthenticationManager()); - } - - public void testPortAuthenticationMappingsDefault() throws Exception - { - _serverConfig.initialise(); - assertEquals("unexpected default number of port/authmanager mappings", 0, _serverConfig.getPortAuthenticationMappings().size()); - } - - public void testPortAuthenticationMappingsWithSingleMapping() throws Exception - { - String testAuthManager = "myauthmanager"; - _config.addProperty("security.port-mappings.port-mapping.port", 1234); - _config.addProperty("security.port-mappings.port-mapping.auth-manager", testAuthManager); - - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - assertEquals("unexpected number of port/authmanager mappings", 1, _serverConfig.getPortAuthenticationMappings().size()); - assertEquals("unexpected mapping for port", testAuthManager, _serverConfig.getPortAuthenticationMappings().get(1234)); - } - - public void testPortAuthenticationMappingsWithManyMapping() throws Exception - { - String testAuthManager1 = "myauthmanager1"; - String testAuthManager2 = "myauthmanager2"; - _config.addProperty("security.port-mappings.port-mapping(-1).port", 1234); - _config.addProperty("security.port-mappings.port-mapping.auth-manager", testAuthManager1); - - _config.addProperty("security.port-mappings.port-mapping(-1).port", 2345); - _config.addProperty("security.port-mappings.port-mapping.auth-manager", testAuthManager2); - - _serverConfig = new ServerConfiguration(_config); - _serverConfig.initialise(); - - assertEquals("unexpected number of port/authmanager mappings", 2, _serverConfig.getPortAuthenticationMappings().size()); - assertEquals("unexpected mapping for port", testAuthManager1, _serverConfig.getPortAuthenticationMappings().get(1234)); - assertEquals("unexpected mapping for port", testAuthManager2, _serverConfig.getPortAuthenticationMappings().get(2345)); - } - - public void testPortAuthenticationMappingWithMissingAuthManager() throws Exception - { - _config.addProperty("security.port-mappings.port-mapping(-1).port", 1234); - // no auth manager defined for port - _serverConfig = new ServerConfiguration(_config); - try - { - _serverConfig.initialise(); - fail("Exception not thrown"); - } - catch(ConfigurationException ce) - { - // PASS - assertEquals("Incorrect error message", - "Validation error: Each port-mapping must have exactly one port and exactly one auth-manager.", - ce.getMessage()); - } - } - - /** - * Convenience method to output required security preamble for broker config - */ - private void writeSecurity(Writer out) throws Exception - { - out.write("\tfalse\n"); - out.write("\t\n"); - out.write("\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\t\torg.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\t\tpasswordFile\n"); - out.write("\t\t\t\t\t\t/dev/null\n"); - out.write("\t\t\t\t\t\n"); - out.write("\t\t\t\t\n"); - out.write("\t\t\t\n"); - out.write("\t\t\n"); - out.write("\t\n"); - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java deleted file mode 100644 index caf74a89ec..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java +++ /dev/null @@ -1,131 +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.configuration; - -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQInternalException; -import org.apache.qpid.AMQSecurityException; -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -/** - * Test of the new Topic configuration processing - */ -public class TopicConfigurationTest extends InternalBrokerBaseCase -{ - - @Override - public void configure() - { - getConfigXml().addProperty("virtualhosts.virtualhost.test.topics.topic.name", "stocks.nyse.appl"); - - getConfigXml().addProperty("virtualhosts.virtualhost.test.topics.topic(1).subscriptionName", getName()+":stockSubscription"); - - getConfigXml().addProperty("virtualhosts.virtualhost.test.topics.topic(2).name", "stocks.nyse.orcl"); - getConfigXml().addProperty("virtualhosts.virtualhost.test.topics.topic(2).subscriptionName", getName()+":stockSubscription"); - } - - /** - * Test that a TopicConfig object is created and attached to the queue when it is bound to the topic exchange. - * - - * @throws ConfigurationException - * @throws AMQSecurityException - */ - public void testTopicCreation() throws ConfigurationException, AMQSecurityException, AMQInternalException - { - Exchange topicExchange = getVirtualHost().getExchangeRegistry().getExchange(ExchangeDefaults.TOPIC_EXCHANGE_NAME); - getVirtualHost().getBindingFactory().addBinding("stocks.nyse.appl", getQueue(), topicExchange, null); - - TopicConfig config = getQueue().getConfiguration().getConfiguration(TopicConfig.class.getName()); - - assertNotNull("Queue should have topic configuration bound to it.", config); - assertEquals("Configuration name not correct", "stocks.nyse.appl", config.getName()); - } - - /** - * Test that a queue created for a subscription correctly has topic - * configuration selected based on the subscription and topic name. - * - * @throws ConfigurationException - * @throws AMQException - */ - public void testSubscriptionWithTopicCreation() throws ConfigurationException, AMQException - { - - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), getName()+":stockSubscription", false, "testowner", - false, false, getVirtualHost(), null); - - getVirtualHost().getQueueRegistry().registerQueue(queue); - Exchange defaultExchange = getVirtualHost().getExchangeRegistry().getDefaultExchange(); - getVirtualHost().getBindingFactory().addBinding(getName(), queue, defaultExchange, null); - - - Exchange topicExchange = getVirtualHost().getExchangeRegistry().getExchange(ExchangeDefaults.TOPIC_EXCHANGE_NAME); - getVirtualHost().getBindingFactory().addBinding("stocks.nyse.orcl", queue, topicExchange, null); - - TopicConfig config = queue.getConfiguration().getConfiguration(TopicConfig.class.getName()); - - assertNotNull("Queue should have topic configuration bound to it.", config); - assertEquals("Configuration subscription name not correct", getName() + ":stockSubscription", config.getSubscriptionName()); - assertEquals("Configuration name not correct", "stocks.nyse.orcl", config.getName()); - - } - - /** - * Test that a queue created for a subscription correctly has topic - * configuration attached here this should be the generic topic section - * with just the subscriptionName - * - * @throws ConfigurationException - * @throws AMQException - */ - public void testSubscriptionCreation() throws ConfigurationException, AMQException - { - - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID() ,getName()+":stockSubscription", false, "testowner", - false, false, getVirtualHost(), null); - - getVirtualHost().getQueueRegistry().registerQueue(queue); - Exchange defaultExchange = getVirtualHost().getExchangeRegistry().getDefaultExchange(); - getVirtualHost().getBindingFactory().addBinding(getName(), queue, defaultExchange, null); - - - Exchange topicExchange = getVirtualHost().getExchangeRegistry().getExchange(ExchangeDefaults.TOPIC_EXCHANGE_NAME); - getVirtualHost().getBindingFactory().addBinding("stocks.nyse.ibm", queue, topicExchange, null); - - TopicConfig config = queue.getConfiguration().getConfiguration(TopicConfig.class.getName()); - - assertNotNull("Queue should have topic configuration bound to it.", config); - assertEquals("Configuration subscription name not correct", getName() + ":stockSubscription", config.getSubscriptionName()); - assertEquals("Configuration name not correct", "#", config.getName()); - - } - - - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java index 50e7f0588b..570bd004c5 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java @@ -19,24 +19,69 @@ */ package org.apache.qpid.server.configuration; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.queue.AMQPriorityQueue; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.test.utils.QpidTestCase; -public class VirtualHostConfigurationTest extends InternalBrokerBaseCase +public class VirtualHostConfigurationTest extends QpidTestCase { + private VirtualHostRegistry _virtualHostRegistry; + private XMLConfiguration _configXml; + private Broker _broker; @Override - public void createBroker() + public void setUp() throws Exception { - // Prevent auto broker startup + super.setUp(); + BrokerTestHelper.setUp(); + _configXml = new XMLConfiguration(); + _configXml.addProperty("virtualhosts.virtualhost(-1).name", getName()); + _configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName()); + _virtualHostRegistry = new VirtualHostRegistry(); + _broker = mock(Broker.class); + when(_broker.getAttribute(Broker.HOUSEKEEPING_CHECK_PERIOD)).thenReturn(30000l); + } + + @Override + public void tearDown() throws Exception + { + try + { + if (_virtualHostRegistry != null) + { + _virtualHostRegistry.close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + } + + private XMLConfiguration getConfigXml() + { + return _configXml; + } + + private VirtualHost createVirtualHost(String hostName) throws Exception + { + Configuration config = getConfigXml().subset("virtualhosts.virtualhost." + XmlConfigurationUtilities.escapeTagName(hostName)); + VirtualHostConfiguration virtualHostConfiguration = new VirtualHostConfiguration(hostName, config, _broker); + return BrokerTestHelper.createVirtualHost(virtualHostConfiguration, _virtualHostRegistry); } public void testQueuePriority() throws Exception @@ -65,11 +110,7 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase getConfigXml().addProperty("virtualhosts.virtualhost.testQueuePriority.queues.queue.ntest.priority", "false"); - // Start the broker now. - super.createBroker(); - - VirtualHost vhost = - ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(getName()); + VirtualHost vhost = createVirtualHost(getName()); // Check that atest was a priority queue with 5 priorities AMQQueue atest = vhost.getQueueRegistry().getQueue(new AMQShortString("atest")); @@ -102,11 +143,7 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase getConfigXml().addProperty("virtualhosts.virtualhost.testQueueAlerts.queues(-1).queue(-1).name(-1)", "btest"); - // Start the broker now. - super.createBroker(); - - VirtualHost vhost = - ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(getName()); + VirtualHost vhost = createVirtualHost(getName()); // Check specifically configured values AMQQueue aTest = vhost.getQueueRegistry().getQueue(new AMQShortString("atest")); @@ -129,11 +166,7 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues.queue.biggles.maximumDeliveryCount", 4); getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues(-1).queue(-1).name", "beetle"); - // Start the broker now. - super.createBroker(); - - // Get vhosts - VirtualHost test = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(getName()); + VirtualHost test = createVirtualHost(getName()); // Enabled specifically assertEquals("Test vhost MDC was configured as enabled", 5 ,test.getConfiguration().getMaxDeliveryCount()); @@ -163,12 +196,8 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues(-1).queue(-1).name", "c3p0"); getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.store.class", TestableMemoryMessageStore.class.getName()); - // Start the broker now. - super.createBroker(); - - // Get vhosts - VirtualHost test = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(getName()); - VirtualHost extra = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(getName() + "Extra"); + VirtualHost test = createVirtualHost(getName()); + VirtualHost extra = createVirtualHost(getName() + "Extra"); // Enabled specifically assertTrue("Test vhost DLQ was configured as enabled", test.getConfiguration().isDeadLetterQueueEnabled()); @@ -215,37 +244,12 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase getConfigXml().addProperty("virtualhosts.virtualhost.testHouseKeepingThreadCount.housekeeping.poolSize", initialPoolSize); - // Start the broker now. - super.createBroker(); - - VirtualHost vhost = - ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(getName()); + VirtualHost vhost = createVirtualHost(getName()); assertEquals("HouseKeeping PoolSize not set correctly.", initialPoolSize, vhost.getHouseKeepingPoolSize()); } - /** - * Test default house keeping tasks - * - * @throws Exception - */ - public void testDefaultHouseKeepingTasks() throws Exception - { - // Start the broker now. - super.createBroker(); - - VirtualHost vhost = - ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(getName()); - - assertEquals("Default houseKeeping task count incorrect.", 2, - vhost.getHouseKeepingTaskCount()); - - // Currently the two are tasks: - // ExpiredMessageTask from VirtualHost - // UpdateTask from the QMF ManagementExchange - } - /** * Test that we can dynamically change the thread pool size * @@ -258,11 +262,7 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase getConfigXml().addProperty("virtualhosts.virtualhost.testDynamicHouseKeepingPoolSizeChange.housekeeping.poolSize", initialPoolSize); - // Start the broker now. - super.createBroker(); - - VirtualHost vhost = - ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost(getName()); + VirtualHost vhost = createVirtualHost(getName()); assertEquals("HouseKeeping PoolSize not set correctly.", initialPoolSize, vhost.getHouseKeepingPoolSize()); @@ -286,7 +286,7 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase try { - super.createBroker(); + createVirtualHost(getName()); fail("Exception not thrown"); } catch(ConfigurationException ce) @@ -309,7 +309,7 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase try { - super.createBroker(); + createVirtualHost(getName()); fail("Exception not thrown"); } catch (ConfigurationException ce) @@ -320,4 +320,41 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase ce.getMessage()); } } + + /* + * Tests that the queues with dots in the names are fully supported. The XML configuration + * had problems with handling the tags containing dots due to the design of the Apache Commons + * Configuration library. The dots need to be escaped when accessing the XML configuration. + */ + public void testDotsInQueueName() throws Exception + { + // Set up vhosts and queue + getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues(-1).queue(-1).name", "dot.in.a.name"); + // Add a single property which is inside the queue tag - the maximum delivery count + getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + ".queues.queue.dot..in..a..name.maximumDeliveryCount", 5); + + VirtualHost test = createVirtualHost(getName()); + + // Check, that the property stored within the tag has been properly loaded + assertEquals("queue with dots in its name has been properly loaded", 5, test.getConfiguration().getQueueConfiguration("dot.in.a.name").getMaxDeliveryCount()); + } + + /* + * Tests that the virtual hosts with dots in the names are fully supported. The XML + * configuration had problems with handling the tags containing dots due to the design + * of the Apache Commons Configuration library. The dots need to be escaped when + * accessing the XML configuration. + */ + public void testDotsInVirtualHostName() throws Exception + { + // Set up vhosts + getConfigXml().addProperty("virtualhosts.virtualhost.name", "dot.in.a.name"); + // Add a single property which is inside the virtual host tag - the message store + getConfigXml().addProperty("virtualhosts.virtualhost.dot..in..a..name.store.class", TestableMemoryMessageStore.class.getName()); + + VirtualHost test = createVirtualHost("dot.in.a.name"); + + // Check, that the property stored within the tag has been properly loaded + assertEquals("virtual host with dots in the name has been properly loaded", TestableMemoryMessageStore.class.getName(), test.getMessageStore().getClass().getName()); + } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/plugins/AbstractConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/plugins/AbstractConfigurationTest.java new file mode 100644 index 0000000000..674abbfeb7 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/plugins/AbstractConfigurationTest.java @@ -0,0 +1,210 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.plugins; + +import org.apache.commons.configuration.CompositeConfiguration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.XMLConfiguration; + +import org.apache.qpid.test.utils.QpidTestCase; + +import java.util.List; + +/** + * Test that verifies that given a Configuration a ConfigurationPlugin can + * process and validate that data. + */ +public class AbstractConfigurationTest extends QpidTestCase +{ + private static final double DOUBLE = 3.14; + private static final long POSITIVE_LONG = 1000; + private static final long NEGATIVE_LONG = -1000; + private static final int LIST_SIZE = 3; + + class TestConfigPlugin extends AbstractConfiguration + { + @Override + public String[] getElementsProcessed() + { + return new String[]{"[@property]", "name", + "positiveLong", "negativeLong", + "true", "list", "double"}; + } + + @Override + public void validateConfiguration() throws ConfigurationException + { + // no validation requried + } + + public String getName() + { + return getStringValue("name"); + } + + public String getProperty() + { + return getStringValue("[@property]"); + } + + + } + + private TestConfigPlugin _plugin; + + @Override + public void setUp() throws Exception + { + // Test does not directly use the AppRegistry but the configured broker + // is required for the correct ConfigurationPlugin processing + super.setUp(); + XMLConfiguration xmlconfig = new XMLConfiguration(); + xmlconfig.addProperty("base.element[@property]", "property"); + xmlconfig.addProperty("base.element.name", "name"); + // We make these strings as that is how they will be read from the file. + xmlconfig.addProperty("base.element.positiveLong", String.valueOf(POSITIVE_LONG)); + xmlconfig.addProperty("base.element.negativeLong", String.valueOf(NEGATIVE_LONG)); + xmlconfig.addProperty("base.element.boolean", String.valueOf(true)); + xmlconfig.addProperty("base.element.double", String.valueOf(DOUBLE)); + for (int i = 0; i < LIST_SIZE; i++) + { + xmlconfig.addProperty("base.element.list", i); + } + + //Use a composite configuration as this is what our broker code uses. + CompositeConfiguration composite = new CompositeConfiguration(); + composite.addConfiguration(xmlconfig); + + _plugin = new TestConfigPlugin(); + + try + { + _plugin.setConfiguration("base.element", composite.subset("base.element")); + } + catch (ConfigurationException e) + { + e.printStackTrace(); + fail(e.toString()); + } + + } + + public void testHasConfiguration() + { + assertTrue("Plugin has no configuration ", _plugin.hasConfiguration()); + _plugin = new TestConfigPlugin(); + assertFalse("Plugins has configuration", _plugin.hasConfiguration()); + } + + public void testValuesRetreived() + { + assertEquals("Name not correct", "name", _plugin.getName()); + assertEquals("Property not correct", "property", _plugin.getProperty()); + } + + public void testContainsPositiveLong() + { + assertTrue("positiveLong is not positive", _plugin.containsPositiveLong("positiveLong")); + assertFalse("NonExistentValue was found", _plugin.containsPositiveLong("NonExistentValue")); + + try + { + _plugin.validatePositiveLong("positiveLong"); + } + catch (ConfigurationException e) + { + fail(e.getMessage()); + } + + try + { + _plugin.validatePositiveLong("negativeLong"); + fail("negativeLong should not be positive"); + } + catch (ConfigurationException e) + { + assertEquals("negativeLong should not be reported as positive", + "TestConfigPlugin: unable to configure invalid negativeLong:" + NEGATIVE_LONG, e.getMessage()); + } + + } + + public void testDouble() + { + assertEquals("Double value not returned", DOUBLE, _plugin.getDoubleValue("double")); + assertEquals("default Double value not returned", 0.0, _plugin.getDoubleValue("NonExistent")); + assertEquals("set default Double value not returned", DOUBLE, _plugin.getDoubleValue("NonExistent", DOUBLE)); + } + + public void testLong() + { + assertTrue("Long value not returned", _plugin.containsLong("positiveLong")); + assertFalse("Long value returned", _plugin.containsLong("NonExistent")); + assertEquals("Long value not returned", POSITIVE_LONG, _plugin.getLongValue("positiveLong")); + assertEquals("default Long value not returned", 0, _plugin.getLongValue("NonExistent")); + assertEquals("set default Long value not returned", NEGATIVE_LONG, _plugin.getLongValue("NonExistent", NEGATIVE_LONG)); + } + + public void testInt() + { + assertTrue("Int value not returned", _plugin.containsInt("positiveLong")); + assertFalse("Int value returned", _plugin.containsInt("NonExistent")); + assertEquals("Int value not returned", (int) POSITIVE_LONG, _plugin.getIntValue("positiveLong")); + assertEquals("default Int value not returned", 0, _plugin.getIntValue("NonExistent")); + assertEquals("set default Int value not returned", (int) NEGATIVE_LONG, _plugin.getIntValue("NonExistent", (int) NEGATIVE_LONG)); + } + + public void testString() + { + assertEquals("String value not returned", "name", _plugin.getStringValue("name")); + assertNull("Null default String value not returned", _plugin.getStringValue("NonExistent", null)); + assertNull("default String value not returned", _plugin.getStringValue("NonExistent")); + assertEquals("default String value not returned", "Default", _plugin.getStringValue("NonExistent", "Default")); + } + + public void testBoolean() + { + assertTrue("Boolean value not returned", _plugin.containsBoolean("boolean")); + assertFalse("Boolean value not returned", _plugin.containsBoolean("NonExistent")); + assertTrue("Boolean value not returned", _plugin.getBooleanValue("boolean")); + assertFalse("default String value not returned", _plugin.getBooleanValue("NonExistent")); + assertTrue("set default String value not returned", _plugin.getBooleanValue("NonExistent", true)); + } + + public void testList() + { + assertTrue("list not found in plugin", _plugin.contains("list")); + List list = _plugin.getListValue("list"); + assertNotNull("Returned list should not be null", list); + assertEquals("List should not be empty", LIST_SIZE, list.size()); + + list = _plugin.getListValue("NonExistent"); + assertNotNull("Returned list should not be null", list); + assertEquals("List is not empty", 0, list.size()); + } + + public void testContains() + { + assertTrue("list not found in plugin", _plugin.contains("list")); + assertFalse("NonExistent found in plugin", _plugin.contains("NonExistent")); + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/plugins/ConfigurationPluginTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/plugins/ConfigurationPluginTest.java deleted file mode 100644 index 14c7b8cb20..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/plugins/ConfigurationPluginTest.java +++ /dev/null @@ -1,210 +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.configuration.plugins; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -import java.util.List; - -/** - * Test that verifies that given a Configuration a ConfigurationPlugin can - * process and validate that data. - */ -public class ConfigurationPluginTest extends InternalBrokerBaseCase -{ - private static final double DOUBLE = 3.14; - private static final long POSITIVE_LONG = 1000; - private static final long NEGATIVE_LONG = -1000; - private static final int LIST_SIZE = 3; - - class ConfigPlugin extends ConfigurationPlugin - { - @Override - public String[] getElementsProcessed() - { - return new String[]{"[@property]", "name", - "positiveLong", "negativeLong", - "true", "list", "double"}; - } - - @Override - public void validateConfiguration() throws ConfigurationException - { - // no validation requried - } - - public String getName() - { - return getStringValue("name"); - } - - public String getProperty() - { - return getStringValue("[@property]"); - } - - - } - - private ConfigPlugin _plugin; - - @Override - public void setUp() throws Exception - { - // Test does not directly use the AppRegistry but the configured broker - // is required for the correct ConfigurationPlugin processing - super.setUp(); - XMLConfiguration xmlconfig = new XMLConfiguration(); - xmlconfig.addProperty("base.element[@property]", "property"); - xmlconfig.addProperty("base.element.name", "name"); - // We make these strings as that is how they will be read from the file. - xmlconfig.addProperty("base.element.positiveLong", String.valueOf(POSITIVE_LONG)); - xmlconfig.addProperty("base.element.negativeLong", String.valueOf(NEGATIVE_LONG)); - xmlconfig.addProperty("base.element.boolean", String.valueOf(true)); - xmlconfig.addProperty("base.element.double", String.valueOf(DOUBLE)); - for (int i = 0; i < LIST_SIZE; i++) - { - xmlconfig.addProperty("base.element.list", i); - } - - //Use a composite configuration as this is what our broker code uses. - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - _plugin = new ConfigPlugin(); - - try - { - _plugin.setConfiguration("base.element", composite.subset("base.element")); - } - catch (ConfigurationException e) - { - e.printStackTrace(); - fail(e.toString()); - } - - } - - public void testHasConfiguration() - { - assertTrue("Plugin has no configuration ", _plugin.hasConfiguration()); - _plugin = new ConfigPlugin(); - assertFalse("Plugins has configuration", _plugin.hasConfiguration()); - } - - public void testValuesRetreived() - { - assertEquals("Name not correct", "name", _plugin.getName()); - assertEquals("Property not correct", "property", _plugin.getProperty()); - } - - public void testContainsPositiveLong() - { - assertTrue("positiveLong is not positive", _plugin.containsPositiveLong("positiveLong")); - assertFalse("NonExistentValue was found", _plugin.containsPositiveLong("NonExistentValue")); - - try - { - _plugin.validatePositiveLong("positiveLong"); - } - catch (ConfigurationException e) - { - fail(e.getMessage()); - } - - try - { - _plugin.validatePositiveLong("negativeLong"); - fail("negativeLong should not be positive"); - } - catch (ConfigurationException e) - { - assertEquals("negativeLong should not be reported as positive", - "ConfigPlugin: unable to configure invalid negativeLong:" + NEGATIVE_LONG, e.getMessage()); - } - - } - - public void testDouble() - { - assertEquals("Double value not returned", DOUBLE, _plugin.getDoubleValue("double")); - assertEquals("default Double value not returned", 0.0, _plugin.getDoubleValue("NonExistent")); - assertEquals("set default Double value not returned", DOUBLE, _plugin.getDoubleValue("NonExistent", DOUBLE)); - } - - public void testLong() - { - assertTrue("Long value not returned", _plugin.containsLong("positiveLong")); - assertFalse("Long value returned", _plugin.containsLong("NonExistent")); - assertEquals("Long value not returned", POSITIVE_LONG, _plugin.getLongValue("positiveLong")); - assertEquals("default Long value not returned", 0, _plugin.getLongValue("NonExistent")); - assertEquals("set default Long value not returned", NEGATIVE_LONG, _plugin.getLongValue("NonExistent", NEGATIVE_LONG)); - } - - public void testInt() - { - assertTrue("Int value not returned", _plugin.containsInt("positiveLong")); - assertFalse("Int value returned", _plugin.containsInt("NonExistent")); - assertEquals("Int value not returned", (int) POSITIVE_LONG, _plugin.getIntValue("positiveLong")); - assertEquals("default Int value not returned", 0, _plugin.getIntValue("NonExistent")); - assertEquals("set default Int value not returned", (int) NEGATIVE_LONG, _plugin.getIntValue("NonExistent", (int) NEGATIVE_LONG)); - } - - public void testString() - { - assertEquals("String value not returned", "name", _plugin.getStringValue("name")); - assertNull("Null default String value not returned", _plugin.getStringValue("NonExistent", null)); - assertNull("default String value not returned", _plugin.getStringValue("NonExistent")); - assertEquals("default String value not returned", "Default", _plugin.getStringValue("NonExistent", "Default")); - } - - public void testBoolean() - { - assertTrue("Boolean value not returned", _plugin.containsBoolean("boolean")); - assertFalse("Boolean value not returned", _plugin.containsBoolean("NonExistent")); - assertTrue("Boolean value not returned", _plugin.getBooleanValue("boolean")); - assertFalse("default String value not returned", _plugin.getBooleanValue("NonExistent")); - assertTrue("set default String value not returned", _plugin.getBooleanValue("NonExistent", true)); - } - - public void testList() - { - assertTrue("list not found in plugin", _plugin.contains("list")); - List list = _plugin.getListValue("list"); - assertNotNull("Returned list should not be null", list); - assertEquals("List should not be empty", LIST_SIZE, list.size()); - - list = _plugin.getListValue("NonExistent"); - assertNotNull("Returned list should not be null", list); - assertEquals("List is not empty", 0, list.size()); - } - - public void testContains() - { - assertTrue("list not found in plugin", _plugin.contains("list")); - assertFalse("NonExistent found in plugin", _plugin.contains("NonExistent")); - } - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java new file mode 100644 index 0000000000..c1ebe26f52 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java @@ -0,0 +1,405 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.UUID; + +import junit.framework.TestCase; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.KeyStore; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; +import org.apache.qpid.server.model.adapter.PortFactory; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.security.group.GroupPrincipalAccessor; +import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; + +public class BrokerRecovererTest extends TestCase +{ + private BrokerRecoverer _brokerRecoverer; + private ConfigurationEntry _brokerEntry = mock(ConfigurationEntry.class); + + private UUID _brokerId = UUID.randomUUID(); + private Map> _brokerEntryChildren = new HashMap>(); + private ConfigurationEntry _authenticationProviderEntry1; + private AuthenticationProvider _authenticationProvider1; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _brokerRecoverer = new BrokerRecoverer(mock(AuthenticationProviderFactory.class), mock(PortFactory.class), mock(StatisticsGatherer.class), + mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.class)); + when(_brokerEntry.getId()).thenReturn(_brokerId); + when(_brokerEntry.getChildren()).thenReturn(_brokerEntryChildren); + + //Add a base AuthenticationProvider for all tests + _authenticationProvider1 = mock(AuthenticationProvider.class); + when(_authenticationProvider1.getName()).thenReturn("authenticationProvider1"); + _authenticationProviderEntry1 = mock(ConfigurationEntry.class); + _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1)); + } + + public void testCreateBrokerAttributes() + { + Map attributes = new HashMap(); + attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test"); + attributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1"); + attributes.put(Broker.ALERT_THRESHOLD_MESSAGE_AGE, 9l); + attributes.put(Broker.ALERT_THRESHOLD_MESSAGE_COUNT, 8l); + attributes.put(Broker.ALERT_THRESHOLD_QUEUE_DEPTH, 7l); + attributes.put(Broker.ALERT_THRESHOLD_MESSAGE_SIZE, 6l); + attributes.put(Broker.ALERT_REPEAT_GAP, 5l); + attributes.put(Broker.FLOW_CONTROL_SIZE_BYTES, 5l); + attributes.put(Broker.FLOW_CONTROL_RESUME_SIZE_BYTES, 3l); + attributes.put(Broker.MAXIMUM_DELIVERY_ATTEMPTS, 2); + attributes.put(Broker.DEAD_LETTER_QUEUE_ENABLED, true); + attributes.put(Broker.HOUSEKEEPING_CHECK_PERIOD, 1l); + attributes.put(Broker.ACL_FILE, "/path/to/acl"); + attributes.put(Broker.SESSION_COUNT_LIMIT, 1000); + attributes.put(Broker.HEART_BEAT_DELAY, 2000); + attributes.put(Broker.STATISTICS_REPORTING_PERIOD, 4000); + attributes.put(Broker.STATISTICS_REPORTING_RESET_ENABLED, true); + + Map entryAttributes = new HashMap(); + for (Map.Entry attribute : attributes.entrySet()) + { + String value = convertToString(attribute.getValue()); + entryAttributes.put(attribute.getKey(), value); + } + + when(_brokerEntry.getAttributes()).thenReturn(entryAttributes); + + final ConfigurationEntry virtualHostEntry = mock(ConfigurationEntry.class); + String typeName = VirtualHost.class.getSimpleName(); + when(virtualHostEntry.getType()).thenReturn(typeName); + _brokerEntryChildren.put(typeName, Arrays.asList(virtualHostEntry)); + final VirtualHost virtualHost = mock(VirtualHost.class); + when(virtualHost.getName()).thenReturn("test"); + + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[] { virtualHostEntry, _authenticationProviderEntry1 }, + new ConfiguredObject[] { virtualHost, _authenticationProvider1 }); + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + assertNotNull(broker); + assertEquals(_brokerId, broker.getId()); + + for (Map.Entry attribute : attributes.entrySet()) + { + Object attributeValue = broker.getAttribute(attribute.getKey()); + assertEquals("Unexpected value of attribute '" + attribute.getKey() + "'", attribute.getValue(), attributeValue); + } + } + + public void testCreateBrokerWithVirtualHost() + { + final ConfigurationEntry virtualHostEntry = mock(ConfigurationEntry.class); + + String typeName = VirtualHost.class.getSimpleName(); + when(virtualHostEntry.getType()).thenReturn(typeName); + _brokerEntryChildren.put(typeName, Arrays.asList(virtualHostEntry)); + + final VirtualHost virtualHost = mock(VirtualHost.class); + + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{virtualHostEntry, _authenticationProviderEntry1}, + new ConfiguredObject[]{virtualHost, _authenticationProvider1}); + + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + + assertNotNull(broker); + assertEquals(_brokerId, broker.getId()); + assertEquals(1, broker.getVirtualHosts().size()); + assertEquals(virtualHost, broker.getVirtualHosts().iterator().next()); + } + + public void testCreateBrokerWithPorts() + { + ConfigurationEntry portEntry = mock(ConfigurationEntry.class); + Port port = mock(Port.class); + _brokerEntryChildren.put(Port.class.getSimpleName(), Arrays.asList(portEntry)); + + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{portEntry, _authenticationProviderEntry1}, + new ConfiguredObject[]{port, _authenticationProvider1}); + + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + + assertNotNull(broker); + assertEquals(_brokerId, broker.getId()); + assertEquals(Collections.singletonList(port), broker.getPorts()); + } + + public void testCreateBrokerWithoutAuthenticationProviderThrowsException() + { + assertNotNull("expected to remove the base entry", _brokerEntryChildren.remove(AuthenticationProvider.class.getSimpleName())); + assertTrue("should be empty", _brokerEntryChildren.isEmpty()); + + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[0], new ConfiguredObject[0]); + + try + { + _brokerRecoverer.create(recovererProvider, _brokerEntry); + fail("should have thrown an exception due to missing authentication provider configuration"); + } + catch(IllegalConfigurationException e) + { + //expected + } + } + + public void testCreateBrokerWithOneAuthenticationProvider() + { + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{_authenticationProviderEntry1}, + new ConfiguredObject[]{_authenticationProvider1}); + + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + + assertNotNull(broker); + assertEquals(_brokerId, broker.getId()); + assertEquals(Collections.singletonList(_authenticationProvider1), broker.getAuthenticationProviders()); + } + + public void testCreateBrokerWithMultipleAuthenticationProvidersAndNoDefaultThrowsException() + { + AuthenticationProvider authenticationProvider2 = mock(AuthenticationProvider.class); + when(authenticationProvider2.getName()).thenReturn("authenticationProvider2"); + ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class); + _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2)); + + Map emptyBrokerAttributes = new HashMap(); + when(_brokerEntry.getAttributes()).thenReturn(emptyBrokerAttributes); + + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{authenticationProviderEntry2, _authenticationProviderEntry1}, + new ConfiguredObject[]{authenticationProvider2, _authenticationProvider1}); + try + { + _brokerRecoverer.create(recovererProvider, _brokerEntry); + fail("should have thrown an exception due to missing authentication provider default"); + } + catch(IllegalConfigurationException e) + { + //expected + } + } + + public void testCreateBrokerWithMultipleAuthenticationProvidersAndPorts() + { + //Create a second authentication provider + AuthenticationProvider authenticationProvider2 = mock(AuthenticationProvider.class); + when(authenticationProvider2.getName()).thenReturn("authenticationProvider2"); + ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class); + _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2)); + + //Set the default authentication provider + Map brokerAtttributes = new HashMap(); + when(_brokerEntry.getAttributes()).thenReturn(brokerAtttributes); + brokerAtttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider2"); + + //Add a couple ports, one with a defined authentication provider and + //one without (which should then use the default) + ConfigurationEntry portEntry1 = mock(ConfigurationEntry.class); + Port port1 = mock(Port.class); + when(port1.getName()).thenReturn("port1"); + when(port1.getPort()).thenReturn(5671); + when(port1.getAttribute(Port.AUTHENTICATION_MANAGER)).thenReturn("authenticationProvider1"); + ConfigurationEntry portEntry2 = mock(ConfigurationEntry.class); + Port port2 = mock(Port.class); + when(port2.getName()).thenReturn("port2"); + when(port2.getPort()).thenReturn(5672); + _brokerEntryChildren.put(Port.class.getSimpleName(), Arrays.asList(portEntry1, portEntry2)); + + RecovererProvider recovererProvider = createRecoveryProvider( + new ConfigurationEntry[]{portEntry1, portEntry2, authenticationProviderEntry2, _authenticationProviderEntry1}, + new ConfiguredObject[]{port1, port2, authenticationProvider2, _authenticationProvider1}); + + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + + assertNotNull(broker); + assertEquals("Unexpected number of authentication providers", 2,broker.getAuthenticationProviders().size()); + + Collection ports = broker.getPorts(); + assertEquals("Unexpected number of ports", 2, ports.size()); + assertTrue(ports.contains(port1)); + assertTrue(ports.contains(port2)); + + verify(port1).setAuthenticationProvider(any(AuthenticationProvider.class)); + verify(port1).setAuthenticationProvider(_authenticationProvider1); + + verify(port2).setAuthenticationProvider(any(AuthenticationProvider.class)); + verify(port2).setAuthenticationProvider(authenticationProvider2); + } + + public void testCreateBrokerAssignsGroupAccessorToAuthenticationProviders() + { + //Create a second authentication provider + AuthenticationProvider authenticationProvider2 = mock(AuthenticationProvider.class); + when(authenticationProvider2.getName()).thenReturn("authenticationProvider2"); + ConfigurationEntry authenticationProviderEntry2 = mock(ConfigurationEntry.class); + _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1, authenticationProviderEntry2)); + + //Set the default authentication provider + Map brokerAtttributes = new HashMap(); + when(_brokerEntry.getAttributes()).thenReturn(brokerAtttributes); + brokerAtttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider2"); + + //Create a group provider + ConfigurationEntry groupProviderEntry = mock(ConfigurationEntry.class); + GroupProvider groupProvider = mock(GroupProvider.class); + _brokerEntryChildren.put(GroupProvider.class.getSimpleName(), Arrays.asList(groupProviderEntry)); + + RecovererProvider recovererProvider = createRecoveryProvider( + new ConfigurationEntry[]{groupProviderEntry, authenticationProviderEntry2, _authenticationProviderEntry1}, + new ConfiguredObject[]{groupProvider, authenticationProvider2, _authenticationProvider1}); + + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + + assertNotNull(broker); + assertEquals("Unexpected number of authentication providers", 2, broker.getAuthenticationProviders().size()); + + //verify that a GroupAcessor was added to the AuthenticationProviders + verify(_authenticationProvider1).setGroupAccessor(any(GroupPrincipalAccessor.class)); + verify(authenticationProvider2).setGroupAccessor(any(GroupPrincipalAccessor.class)); + } + + public void testCreateBrokerWithGroupProvider() + { + ConfigurationEntry groupProviderEntry = mock(ConfigurationEntry.class); + GroupProvider groupProvider = mock(GroupProvider.class); + _brokerEntryChildren.put(GroupProvider.class.getSimpleName(), Arrays.asList(groupProviderEntry)); + + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{groupProviderEntry, _authenticationProviderEntry1}, + new ConfiguredObject[]{groupProvider, _authenticationProvider1}); + + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + + assertNotNull(broker); + assertEquals(_brokerId, broker.getId()); + assertEquals(Collections.singletonList(groupProvider), broker.getGroupProviders()); + } + + public void testCreateBrokerWithPlugins() + { + ConfigurationEntry pluginEntry = mock(ConfigurationEntry.class); + Plugin plugin = mock(Plugin.class); + _brokerEntryChildren.put(Plugin.class.getSimpleName(), Arrays.asList(pluginEntry)); + + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{pluginEntry, _authenticationProviderEntry1}, + new ConfiguredObject[]{plugin, _authenticationProvider1}); + + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + + assertNotNull(broker); + assertEquals(_brokerId, broker.getId()); + assertEquals(Collections.singleton(plugin), new HashSet(broker.getChildren(Plugin.class))); + } + + public void testCreateBrokerWithKeyStores() + { + ConfigurationEntry pluginEntry = mock(ConfigurationEntry.class); + KeyStore keyStore = mock(KeyStore.class); + _brokerEntryChildren.put(KeyStore.class.getSimpleName(), Arrays.asList(pluginEntry)); + + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{pluginEntry, _authenticationProviderEntry1}, + new ConfiguredObject[]{keyStore, _authenticationProvider1}); + + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + + assertNotNull(broker); + assertEquals(_brokerId, broker.getId()); + assertEquals(Collections.singleton(keyStore), new HashSet(broker.getChildren(KeyStore.class))); + } + + public void testCreateBrokerWithTrustStores() + { + ConfigurationEntry pluginEntry = mock(ConfigurationEntry.class); + TrustStore trustStore = mock(TrustStore.class); + _brokerEntryChildren.put(TrustStore.class.getSimpleName(), Arrays.asList(pluginEntry)); + + RecovererProvider recovererProvider = createRecoveryProvider(new ConfigurationEntry[]{pluginEntry, _authenticationProviderEntry1}, + new ConfiguredObject[]{trustStore, _authenticationProvider1}); + + Broker broker = _brokerRecoverer.create(recovererProvider, _brokerEntry); + + assertNotNull(broker); + assertEquals(_brokerId, broker.getId()); + assertEquals(Collections.singleton(trustStore), new HashSet(broker.getChildren(TrustStore.class))); + } + + private String convertToString(Object attributeValue) + { + return String.valueOf(attributeValue); + } + + private RecovererProvider createRecoveryProvider(final ConfigurationEntry[] entries, final ConfiguredObject[] objectsToRecoverer) + { + RecovererProvider recovererProvider = new RecovererProvider() + { + @Override + public ConfiguredObjectRecoverer getRecoverer(String type) + { + @SuppressWarnings({ "unchecked", "rawtypes" }) + final ConfiguredObjectRecoverer recovever = new ConfiguredObjectRecoverer() + { + @Override + public ConfiguredObject create(RecovererProvider recovererProvider, ConfigurationEntry entry, ConfiguredObject... parents) + { + for (int i = 0; i < entries.length; i++) + { + ConfigurationEntry e = entries[i]; + if (entry == e) + { + return objectsToRecoverer[i]; + } + } + return null; + } + }; + + return recovever; + } + }; + return recovererProvider; + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java new file mode 100644 index 0000000000..c95f67beb9 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java @@ -0,0 +1,62 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import static org.mockito.Mockito.mock; +import junit.framework.TestCase; + +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; + +public class DefaultRecovererProviderTest extends TestCase +{ + public void testGetRecoverer() + { + String[] supportedTypes = {Broker.class.getSimpleName(), + VirtualHost.class.getSimpleName(), AuthenticationProvider.class.getSimpleName(), + GroupProvider.class.getSimpleName(), Plugin.class.getSimpleName(), Port.class.getSimpleName()}; + + // mocking the required object + StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class); + VirtualHostRegistry virtualHostRegistry = mock(VirtualHostRegistry.class); + LogRecorder logRecorder = mock(LogRecorder.class); + RootMessageLogger rootMessageLogger = mock(RootMessageLogger.class); + TaskExecutor taskExecutor = mock(TaskExecutor.class); + + DefaultRecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, taskExecutor); + for (String configuredObjectType : supportedTypes) + { + ConfiguredObjectRecoverer recovever = provider.getRecoverer(configuredObjectType); + assertNotNull("Null recoverer for type: " + configuredObjectType, recovever); + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java new file mode 100644 index 0000000000..6713574e4b --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/GroupProviderRecovererTest.java @@ -0,0 +1,97 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; +import static org.mockito.Mockito.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.plugin.GroupManagerFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; +import org.apache.qpid.server.security.group.GroupManager; + +import junit.framework.TestCase; + +public class GroupProviderRecovererTest extends TestCase +{ + + private UUID _id; + private Map _attributes; + + private GroupManagerFactory _factory; + private QpidServiceLoader _groupManagerServiceLoader; + private Broker _broker; + private ConfigurationEntry _configurationEntry; + + @SuppressWarnings("unchecked") + protected void setUp() throws Exception + { + super.setUp(); + _id = UUID.randomUUID(); + _attributes = new HashMap(); + + _factory = mock(GroupManagerFactory.class); + + _groupManagerServiceLoader = mock(QpidServiceLoader.class); + when(_groupManagerServiceLoader.instancesOf(GroupManagerFactory.class)).thenReturn(Collections.singletonList(_factory )); + + _broker = mock(Broker.class); + + _configurationEntry = mock(ConfigurationEntry.class); + when(_configurationEntry.getId()).thenReturn(_id); + when(_configurationEntry.getAttributes()).thenReturn(_attributes); + } + + public void testCreate() + { + GroupManager groupManager = mock(GroupManager.class); + String name = groupManager.getClass().getSimpleName(); + when(_factory.createInstance(_attributes)).thenReturn(groupManager); + GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupManagerServiceLoader); + GroupProvider groupProvider = groupProviderRecoverer.create(null, _configurationEntry, _broker); + assertNotNull("Null group provider", groupProvider); + assertEquals("Unexpected name", name, groupProvider.getName()); + assertEquals("Unexpected ID", _id, groupProvider.getId()); + } + + public void testCreateThrowsExceptionWhenNoGroupManagerIsCreated() + { + when(_factory.createInstance(_attributes)).thenReturn(null); + + GroupProviderRecoverer groupProviderRecoverer = new GroupProviderRecoverer(_groupManagerServiceLoader); + try + { + groupProviderRecoverer.create(null, _configurationEntry, _broker); + fail("Configuration exception should be thrown when group manager is not created"); + } + catch(IllegalConfigurationException e) + { + // pass + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/KeyStoreRecovererTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/KeyStoreRecovererTest.java new file mode 100644 index 0000000000..0d7dc1bb06 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/KeyStoreRecovererTest.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.configuration.startup; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.KeyStore; +import org.apache.qpid.server.model.TrustStore; + +import junit.framework.TestCase; + +public class KeyStoreRecovererTest extends TestCase +{ + + public void testCreateWithAllAttributesProvided() + { + Map attributes = getKeyStoreAttributes(); + + UUID id = UUID.randomUUID(); + Broker broker = mock(Broker.class); + ConfigurationEntry entry = mock(ConfigurationEntry.class); + when(entry.getAttributes()).thenReturn(attributes); + when(entry.getId()).thenReturn(id); + + KeyStoreRecoverer recovever = new KeyStoreRecoverer(); + + KeyStore KeyStore = recovever.create(null, entry, broker); + assertNotNull("Key store configured object is not created", KeyStore); + assertEquals(id, KeyStore.getId()); + assertEquals("my-secret-password", KeyStore.getPassword()); + + assertNull("Password was unexpectedly returned from configured object", KeyStore.getAttribute(TrustStore.PASSWORD)); + + // password attribute should not be exposed by a key store configured object + // so, we should set password value to null in the map being used to create the key store configured object + attributes.put(KeyStore.PASSWORD, null); + for (Map.Entry attribute : attributes.entrySet()) + { + Object attributeValue = KeyStore.getAttribute(attribute.getKey()); + assertEquals("Unexpected value of attribute '" + attribute.getKey() + "'", attribute.getValue(), attributeValue); + } + } + + private Map getKeyStoreAttributes() + { + Map attributes = new HashMap(); + attributes.put(KeyStore.NAME, getName()); + attributes.put(KeyStore.PATH, "/path/to/KeyStore"); + attributes.put(KeyStore.PASSWORD, "my-secret-password"); + attributes.put(KeyStore.TYPE, "NON-JKS"); + attributes.put(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD"); + attributes.put(KeyStore.CERTIFICATE_ALIAS, "my-cert-alias"); + attributes.put(KeyStore.DESCRIPTION, "description"); + return attributes; + } + + public void testCreateWithMissedRequiredAttributes() + { + Map attributes = getKeyStoreAttributes(); + + UUID id = UUID.randomUUID(); + Broker broker = mock(Broker.class); + ConfigurationEntry entry = mock(ConfigurationEntry.class); + when(entry.getId()).thenReturn(id); + + KeyStoreRecoverer recovever = new KeyStoreRecoverer(); + + String[] mandatoryProperties = {KeyStore.NAME, KeyStore.PATH, KeyStore.PASSWORD}; + for (int i = 0; i < mandatoryProperties.length; i++) + { + Map properties = new HashMap(attributes); + properties.remove(mandatoryProperties[i]); + when(entry.getAttributes()).thenReturn(properties); + try + { + recovever.create(null, entry, broker); + fail("Cannot create key store without a " + mandatoryProperties[i]); + } + catch(IllegalArgumentException e) + { + // pass + } + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PluginRecovererTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PluginRecovererTest.java new file mode 100644 index 0000000000..42fd742407 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PluginRecovererTest.java @@ -0,0 +1,117 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import junit.framework.TestCase; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.plugin.PluginFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +public class PluginRecovererTest extends TestCase +{ + private UUID _id; + private Map _attributes; + + private PluginFactory _factory; + private QpidServiceLoader _pluginFactoryServiceLoader; + private Broker _broker; + private ConfigurationEntry _configurationEntry; + + @SuppressWarnings("unchecked") + protected void setUp() throws Exception + { + super.setUp(); + _id = UUID.randomUUID(); + _attributes = new HashMap(); + + _factory = mock(PluginFactory.class); + + _pluginFactoryServiceLoader = mock(QpidServiceLoader.class); + when(_pluginFactoryServiceLoader.instancesOf(PluginFactory.class)).thenReturn(Collections.singletonList(_factory )); + + _broker = mock(Broker.class); + + _configurationEntry = mock(ConfigurationEntry.class); + when(_configurationEntry.getId()).thenReturn(_id); + when(_configurationEntry.getAttributes()).thenReturn(_attributes); + } + + public void testCreate() + { + Plugin pluginFromFactory = mock(Plugin.class); + when(pluginFromFactory.getId()).thenReturn(_id); + when(_factory.createInstance(_id, _attributes, _broker)).thenReturn(pluginFromFactory); + + PluginRecoverer pluginRecoverer = new PluginRecoverer(_pluginFactoryServiceLoader); + ConfiguredObject pluginFromRecoverer = pluginRecoverer.create(null, _configurationEntry, _broker); + assertNotNull("Null group provider", pluginFromRecoverer); + assertSame("Unexpected plugin", pluginFromFactory, pluginFromRecoverer); + assertEquals("Unexpected ID", _id, pluginFromRecoverer.getId()); + } + + public void testCreateThrowsExceptionForUnexpectedId() + { + Plugin pluginFromFactory = mock(Plugin.class); + when(pluginFromFactory.getId()).thenReturn(UUID.randomUUID()); + when(_factory.createInstance(_id, _attributes, _broker)).thenReturn(pluginFromFactory); + + PluginRecoverer pluginRecoverer = new PluginRecoverer(_pluginFactoryServiceLoader); + try + { + pluginRecoverer.create(null, _configurationEntry, _broker); + fail("An exception should be thrown for incorrect id"); + } + catch(IllegalStateException e) + { + //pass + } + } + + public void testCreateThrowsExceptionWhenNoPluginIsCreated() + { + when(_factory.createInstance(_id, _attributes, _broker)).thenReturn(null); + + PluginRecoverer pluginRecoverer = new PluginRecoverer(_pluginFactoryServiceLoader); + try + { + pluginRecoverer.create(null, _configurationEntry, _broker); + fail("Configuration exception should be thrown when plugin is not created"); + } + catch(IllegalConfigurationException e) + { + // pass + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java new file mode 100644 index 0000000000..3b64f45c80 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/TrustStoreRecovererTest.java @@ -0,0 +1,108 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.test.utils.QpidTestCase; + +public class TrustStoreRecovererTest extends QpidTestCase +{ + public void testCreateWithAllAttributesProvided() + { + Map attributes = getTrustStoreAttributes(); + + UUID id = UUID.randomUUID(); + Broker broker = mock(Broker.class); + ConfigurationEntry entry = mock(ConfigurationEntry.class); + when(entry.getAttributes()).thenReturn(attributes); + when(entry.getId()).thenReturn(id); + + TrustStoreRecoverer recovever = new TrustStoreRecoverer(); + + TrustStore trustStore = recovever.create(null, entry, broker); + assertNotNull("Trust store configured object is not created", trustStore); + assertEquals(id, trustStore.getId()); + assertEquals("my-secret-password", trustStore.getPassword()); + + assertNull("Password was unexpectedly returned from configured object", trustStore.getAttribute(TrustStore.PASSWORD)); + + // password attribute should not be exposed by a trust store configured object + // so, we should set password value to null in the map being used to create the trust store configured object + attributes.put(TrustStore.PASSWORD, null); + for (Map.Entry attribute : attributes.entrySet()) + { + Object attributeValue = trustStore.getAttribute(attribute.getKey()); + assertEquals("Unexpected value of attribute '" + attribute.getKey() + "'", attribute.getValue(), attributeValue); + } + } + + private Map getTrustStoreAttributes() + { + Map attributes = new HashMap(); + attributes.put(TrustStore.NAME, getName()); + attributes.put(TrustStore.PATH, "/path/to/truststore"); + attributes.put(TrustStore.PASSWORD, "my-secret-password"); + attributes.put(TrustStore.TYPE, "NON-JKS"); + attributes.put(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD"); + attributes.put(TrustStore.DESCRIPTION, "Description"); + return attributes; + } + + public void testCreateWithMissedRequiredAttributes() + { + Map attributes = getTrustStoreAttributes(); + + UUID id = UUID.randomUUID(); + Broker broker = mock(Broker.class); + ConfigurationEntry entry = mock(ConfigurationEntry.class); + when(entry.getAttributes()).thenReturn(attributes); + when(entry.getId()).thenReturn(id); + + TrustStoreRecoverer recovever = new TrustStoreRecoverer(); + + String[] mandatoryProperties = {TrustStore.NAME, TrustStore.PATH, TrustStore.PASSWORD}; + for (int i = 0; i < mandatoryProperties.length; i++) + { + Map properties = new HashMap(attributes); + properties.remove(mandatoryProperties[i]); + when(entry.getAttributes()).thenReturn(properties); + try + { + recovever.create(null, entry, broker); + fail("Cannot create key store without a " + mandatoryProperties[i]); + } + catch(IllegalArgumentException e) + { + // pass + } + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java new file mode 100644 index 0000000000..57d219f85f --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java @@ -0,0 +1,124 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.stats.StatisticsGatherer; + +public class VirtualHostRecovererTest extends TestCase +{ + public void testCreate() + { + StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class); + SecurityManager securityManager = mock(SecurityManager.class); + ConfigurationEntry entry = mock(ConfigurationEntry.class); + Broker parent = mock(Broker.class); + when(parent.getSecurityManager()).thenReturn(securityManager); + + VirtualHostRecoverer recoverer = new VirtualHostRecoverer(statisticsGatherer); + Map attributes = new HashMap(); + attributes.put(VirtualHost.NAME, getName()); + attributes.put(VirtualHost.CONFIG_PATH, "/path/to/virtualhost.xml"); + when(entry.getAttributes()).thenReturn(attributes); + + VirtualHost host = recoverer.create(null, entry, parent); + + assertNotNull("Null is returned", host); + assertEquals("Unexpected name", getName(), host.getName()); + } + + public void testCreateVirtualHostFromStoreConfigAtrributes() + { + StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class); + SecurityManager securityManager = mock(SecurityManager.class); + ConfigurationEntry entry = mock(ConfigurationEntry.class); + Broker parent = mock(Broker.class); + when(parent.getSecurityManager()).thenReturn(securityManager); + + VirtualHostRecoverer recoverer = new VirtualHostRecoverer(statisticsGatherer); + Map attributes = new HashMap(); + attributes.put(VirtualHost.NAME, getName()); + attributes.put(VirtualHost.STORE_PATH, "/path/to/virtualhost/store"); + attributes.put(VirtualHost.STORE_TYPE, "DERBY"); + when(entry.getAttributes()).thenReturn(attributes); + + VirtualHost host = recoverer.create(null, entry, parent); + + assertNotNull("Null is returned", host); + assertEquals("Unexpected name", getName(), host.getName()); + } + + public void testCreateWithoutMandatoryAttributesResultsInException() + { + Map attributes = new HashMap(); + attributes.put(VirtualHost.NAME, getName()); + attributes.put(VirtualHost.CONFIG_PATH, "/path/to/virtualhost.xml"); + String[] mandatoryAttributes = {VirtualHost.NAME, VirtualHost.CONFIG_PATH}; + + checkMandatoryAttributesAreValidated(mandatoryAttributes, attributes); + + attributes = new HashMap(); + attributes.put(VirtualHost.NAME, getName()); + attributes.put(VirtualHost.STORE_PATH, "/path/to/store"); + attributes.put(VirtualHost.STORE_TYPE, "DERBY"); + mandatoryAttributes = new String[]{VirtualHost.NAME, VirtualHost.STORE_PATH, VirtualHost.STORE_TYPE}; + + checkMandatoryAttributesAreValidated(mandatoryAttributes, attributes); + } + + public void checkMandatoryAttributesAreValidated(String[] mandatoryAttributes, Map attributes) + { + StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class); + SecurityManager securityManager = mock(SecurityManager.class); + ConfigurationEntry entry = mock(ConfigurationEntry.class); + Broker parent = mock(Broker.class); + when(parent.getSecurityManager()).thenReturn(securityManager); + VirtualHostRecoverer recoverer = new VirtualHostRecoverer(statisticsGatherer); + + for (String name : mandatoryAttributes) + { + Map copy = new HashMap(attributes); + copy.remove(name); + when(entry.getAttributes()).thenReturn(copy); + try + { + recoverer.create(null, entry, parent); + fail("Cannot create a virtual host without a manadatory attribute " + name); + } + catch(IllegalConfigurationException e) + { + // pass + } + } + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java new file mode 100644 index 0000000000..b357c0b8e9 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java @@ -0,0 +1,392 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.store; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.server.model.KeyStore; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.TrustStore; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager; +import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager; +import org.apache.qpid.test.utils.QpidTestCase; + +public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase +{ + private ConfigurationEntryStore _store; + + private UUID _brokerId; + private UUID _virtualHostId; + private UUID _authenticationProviderId; + + private Map _brokerAttributes; + private Map _virtualHostAttributes; + private Map _authenticationProviderAttributes; + + public void setUp() throws Exception + { + super.setUp(); + + _brokerId = UUID.randomUUID(); + _brokerAttributes = new HashMap(); + _brokerAttributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test"); + _brokerAttributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1"); + _brokerAttributes.put(Broker.ALERT_THRESHOLD_MESSAGE_AGE, 9); + _brokerAttributes.put(Broker.ALERT_THRESHOLD_MESSAGE_COUNT, 8); + _brokerAttributes.put(Broker.ALERT_THRESHOLD_QUEUE_DEPTH, 7); + _brokerAttributes.put(Broker.ALERT_THRESHOLD_MESSAGE_SIZE, 6); + _brokerAttributes.put(Broker.ALERT_REPEAT_GAP, 5); + _brokerAttributes.put(Broker.FLOW_CONTROL_SIZE_BYTES, 5); + _brokerAttributes.put(Broker.FLOW_CONTROL_RESUME_SIZE_BYTES, 3); + _brokerAttributes.put(Broker.MAXIMUM_DELIVERY_ATTEMPTS, 2); + _brokerAttributes.put(Broker.DEAD_LETTER_QUEUE_ENABLED, true); + _brokerAttributes.put(Broker.HOUSEKEEPING_CHECK_PERIOD, 1); + _brokerAttributes.put(Broker.ACL_FILE, "/path/to/acl"); + _brokerAttributes.put(Broker.SESSION_COUNT_LIMIT, 1000); + _brokerAttributes.put(Broker.HEART_BEAT_DELAY, 2000); + _brokerAttributes.put(Broker.STATISTICS_REPORTING_PERIOD, 4000); + _brokerAttributes.put(Broker.STATISTICS_REPORTING_RESET_ENABLED, true); + + _virtualHostId = UUID.randomUUID(); + _virtualHostAttributes = new HashMap(); + _virtualHostAttributes.put(VirtualHost.NAME, "test"); + _virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/test"); + + _authenticationProviderId = UUID.randomUUID(); + _authenticationProviderAttributes = new HashMap(); + _authenticationProviderAttributes.put(AuthenticationProvider.NAME, "authenticationProvider1"); + _authenticationProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, AnonymousAuthenticationManager.class.getSimpleName()); + + _store = createStore(_brokerId, _brokerAttributes); + addConfiguration(_virtualHostId, VirtualHost.class.getSimpleName(), _virtualHostAttributes); + addConfiguration(_authenticationProviderId, AuthenticationProvider.class.getSimpleName(), _authenticationProviderAttributes); + } + + // ??? perhaps it should not be abstract + protected abstract ConfigurationEntryStore createStore(UUID brokerId, Map brokerAttributes) throws Exception; + + protected abstract void addConfiguration(UUID id, String type, Map attributes); + + protected ConfigurationEntryStore getStore() + { + return _store; + } + + public void testGetRootEntry() + { + ConfigurationEntry brokerConfigEntry = _store.getRootEntry(); + assertNotNull("Root entry does not exist", brokerConfigEntry); + assertEquals("Unexpected id", _brokerId, brokerConfigEntry.getId()); + assertEquals("Unexpected type ", Broker.class.getSimpleName(), brokerConfigEntry.getType()); + Map attributes = brokerConfigEntry.getAttributes(); + assertNotNull("Attributes cannot be null", attributes); + assertEquals("Unexpected attributes", _brokerAttributes, attributes); + } + + public void testGetEntry() + { + ConfigurationEntry authenticationProviderConfigEntry = _store.getEntry(_authenticationProviderId); + assertNotNull("Provider with id " + _authenticationProviderId + " should exist", authenticationProviderConfigEntry); + assertEquals("Unexpected id", _authenticationProviderId, authenticationProviderConfigEntry.getId()); + assertEquals("Unexpected type ", AuthenticationProvider.class.getSimpleName(), authenticationProviderConfigEntry.getType()); + Map attributes = authenticationProviderConfigEntry.getAttributes(); + assertNotNull("Attributes cannot be null", attributes); + assertEquals("Unexpected attributes", _authenticationProviderAttributes, attributes); + } + + public void testRemove() + { + Map virtualHostAttributes = new HashMap(); + virtualHostAttributes.put(VirtualHost.NAME, getName()); + virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config"); + UUID virtualHostId = UUID.randomUUID(); + addConfiguration(virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes); + + assertNotNull("Virtual host with id " + virtualHostId + " should exist", _store.getEntry(virtualHostId)); + + _store.remove(virtualHostId); + assertNull("Authentication provider configuration should be removed", _store.getEntry(virtualHostId)); + } + + public void testRemoveMultipleEntries() + { + Map virtualHost1Attributes = new HashMap(); + virtualHost1Attributes.put(VirtualHost.NAME, "test1"); + virtualHost1Attributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config1"); + UUID virtualHost1Id = UUID.randomUUID(); + addConfiguration(virtualHost1Id, VirtualHost.class.getSimpleName(), virtualHost1Attributes); + + Map virtualHost2Attributes = new HashMap(); + virtualHost2Attributes.put(VirtualHost.NAME, "test1"); + virtualHost2Attributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config2"); + UUID virtualHost2Id = UUID.randomUUID(); + addConfiguration(virtualHost2Id, VirtualHost.class.getSimpleName(), virtualHost2Attributes); + + assertNotNull("Virtual host with id " + virtualHost1Id + " should exist", _store.getEntry(virtualHost1Id)); + assertNotNull("Virtual host with id " + virtualHost2Id + " should exist", _store.getEntry(virtualHost2Id)); + + UUID[] deletedIds = _store.remove(virtualHost1Id, virtualHost2Id); + assertNotNull("Unexpected deleted ids", deletedIds); + assertEquals("Unexpected id of first deleted virtual host", virtualHost1Id , deletedIds[0]); + assertEquals("Unexpected id of second deleted virtual host", virtualHost2Id , deletedIds[1]); + assertNull("First virtual host configuration should be removed", _store.getEntry(virtualHost1Id)); + assertNull("Second virtual host configuration should be removed", _store.getEntry(virtualHost2Id)); + } + + public void testSaveBroker() + { + ConfigurationEntry brokerConfigEntry = _store.getRootEntry(); + Map attributes = new HashMap(); + attributes.put(Broker.DEFAULT_VIRTUAL_HOST, "test"); + attributes.put(Broker.DEFAULT_AUTHENTICATION_PROVIDER, "authenticationProvider1"); + attributes.put(Broker.ALERT_THRESHOLD_MESSAGE_AGE, 19); + attributes.put(Broker.ALERT_THRESHOLD_MESSAGE_COUNT, 18); + attributes.put(Broker.ALERT_THRESHOLD_QUEUE_DEPTH, 17); + attributes.put(Broker.ALERT_THRESHOLD_MESSAGE_SIZE, 16); + attributes.put(Broker.ALERT_REPEAT_GAP, 15); + attributes.put(Broker.FLOW_CONTROL_SIZE_BYTES, 15); + attributes.put(Broker.FLOW_CONTROL_RESUME_SIZE_BYTES, 13); + attributes.put(Broker.MAXIMUM_DELIVERY_ATTEMPTS, 12); + attributes.put(Broker.DEAD_LETTER_QUEUE_ENABLED, false); + attributes.put(Broker.HOUSEKEEPING_CHECK_PERIOD, 11); + attributes.put(Broker.ACL_FILE, "/path/to/acl1"); + attributes.put(Broker.SESSION_COUNT_LIMIT, 11000); + attributes.put(Broker.HEART_BEAT_DELAY, 12000); + attributes.put(Broker.STATISTICS_REPORTING_PERIOD, 14000); + attributes.put(Broker.STATISTICS_REPORTING_RESET_ENABLED, false); + ConfigurationEntry updatedBrokerEntry = new ConfigurationEntry(_brokerId, Broker.class.getSimpleName(), attributes, + brokerConfigEntry.getChildrenIds(), _store); + + _store.save(updatedBrokerEntry); + + ConfigurationEntry newBrokerConfigEntry = _store.getRootEntry(); + assertNotNull("Root entry does not exist", newBrokerConfigEntry); + assertEquals("Unexpected id", _brokerId, newBrokerConfigEntry.getId()); + assertEquals("Unexpected type ", Broker.class.getSimpleName(), newBrokerConfigEntry.getType()); + Map newBrokerattributes = newBrokerConfigEntry.getAttributes(); + assertNotNull("Attributes cannot be null", newBrokerattributes); + assertEquals("Unexpected attributes", attributes, newBrokerattributes); + } + + public void testSaveNewVirtualHost() + { + Map virtualHostAttributes = new HashMap(); + virtualHostAttributes.put(VirtualHost.NAME, "test1"); + virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config1"); + UUID virtualHostId = UUID.randomUUID(); + ConfigurationEntry hostEntry = new ConfigurationEntry(virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes, + Collections. emptySet(), _store); + + _store.save(hostEntry); + + ConfigurationEntry configurationEntry = _store.getEntry(virtualHostId); + assertEquals("Unexpected virtual host configuration", hostEntry, configurationEntry); + assertEquals("Unexpected type", VirtualHost.class.getSimpleName(), configurationEntry.getType()); + assertEquals("Unexpected virtual host attributes", hostEntry.getAttributes(), configurationEntry.getAttributes()); + assertTrue("Unexpected virtual host children found", hostEntry.getChildrenIds().isEmpty()); + } + + public void testSaveExistingVirtualHost() + { + ConfigurationEntry hostEntry = _store.getEntry(_virtualHostId); + assertNotNull("Host configuration is not found", hostEntry); + + Map virtualHostAttributes = new HashMap(); + virtualHostAttributes.put(VirtualHost.NAME, "test"); + virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/new/phantom/test/configuration"); + + ConfigurationEntry updatedEntry = new ConfigurationEntry(_virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes, + hostEntry.getChildrenIds(), _store); + _store.save(updatedEntry); + + ConfigurationEntry newHostEntry = _store.getEntry(_virtualHostId); + assertEquals("Unexpected virtual host configuration", updatedEntry, newHostEntry); + assertEquals("Unexpected type", VirtualHost.class.getSimpleName(), newHostEntry.getType()); + assertEquals("Unexpected virtual host attributes", updatedEntry.getAttributes(), newHostEntry.getAttributes()); + assertEquals("Unexpected virtual host children found", updatedEntry.getChildrenIds(), newHostEntry.getChildrenIds()); + } + + public void testSaveNewAuthenticationProvider() + { + UUID authenticationProviderId = UUID.randomUUID(); + Map authenticationProviderAttributes = new HashMap(); + authenticationProviderAttributes.put(AuthenticationProvider.NAME, "authenticationProvider1"); + authenticationProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, ExternalAuthenticationManager.class.getSimpleName()); + ConfigurationEntry providerEntry = new ConfigurationEntry(authenticationProviderId, AuthenticationProvider.class.getSimpleName(), + authenticationProviderAttributes, Collections. emptySet(), _store); + + _store.save(providerEntry); + + ConfigurationEntry storeEntry = _store.getEntry(authenticationProviderId); + assertEquals("Unexpected provider configuration", providerEntry, storeEntry); + assertEquals("Unexpected type", AuthenticationProvider.class.getSimpleName(), storeEntry.getType()); + assertEquals("Unexpected provider attributes", providerEntry.getAttributes(), storeEntry.getAttributes()); + assertTrue("Unexpected provider children found", storeEntry.getChildrenIds().isEmpty()); + } + + public void testSaveExistingAuthenticationProvider() + { + ConfigurationEntry providerEntry = _store.getEntry(_authenticationProviderId); + assertNotNull("provider configuration is not found", providerEntry); + + Map authenticationProviderAttributes = new HashMap(); + authenticationProviderAttributes.put(AuthenticationProvider.NAME, "authenticationProvider1"); + authenticationProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, ExternalAuthenticationManager.class.getSimpleName()); + ConfigurationEntry updatedEntry = new ConfigurationEntry(_authenticationProviderId, AuthenticationProvider.class.getSimpleName(), + authenticationProviderAttributes, Collections. emptySet(), _store); + _store.save(updatedEntry); + + ConfigurationEntry storeEntry = _store.getEntry(_authenticationProviderId); + assertEquals("Unexpected provider configuration", updatedEntry, storeEntry); + assertEquals("Unexpected type", AuthenticationProvider.class.getSimpleName(), storeEntry.getType()); + assertEquals("Unexpected provider attributes", updatedEntry.getAttributes(), storeEntry.getAttributes()); + assertTrue("Unexpected provider children found", storeEntry.getChildrenIds().isEmpty()); + } + + public void testSaveTrustStore() + { + UUID trustStoreId = UUID.randomUUID(); + Map attributes = new HashMap(); + attributes.put(TrustStore.NAME, getName()); + attributes.put(TrustStore.PATH, "/path/to/truststore"); + attributes.put(TrustStore.PASSWORD, "my-secret-password"); + attributes.put(TrustStore.TYPE, "NON-JKS"); + attributes.put(TrustStore.KEY_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD"); + attributes.put(TrustStore.DESCRIPTION, "Description"); + + ConfigurationEntry trustStoreEntry = new ConfigurationEntry(trustStoreId, TrustStore.class.getSimpleName(), attributes, + Collections. emptySet(), _store); + + _store.save(trustStoreEntry); + + ConfigurationEntry storeEntry = _store.getEntry(trustStoreId); + assertEquals("Unexpected trust store configuration", trustStoreEntry, storeEntry); + assertEquals("Unexpected type", TrustStore.class.getSimpleName(), storeEntry.getType()); + assertEquals("Unexpected provider attributes", trustStoreEntry.getAttributes(), storeEntry.getAttributes()); + assertTrue("Unexpected provider children found", storeEntry.getChildrenIds().isEmpty()); + } + + public void testSaveKeyStore() + { + UUID keyStoreId = UUID.randomUUID(); + Map attributes = new HashMap(); + attributes.put(KeyStore.NAME, getName()); + attributes.put(KeyStore.PATH, "/path/to/truststore"); + attributes.put(KeyStore.PASSWORD, "my-secret-password"); + attributes.put(KeyStore.TYPE, "NON-JKS"); + attributes.put(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD"); + attributes.put(KeyStore.DESCRIPTION, "Description"); + attributes.put(KeyStore.CERTIFICATE_ALIAS, "Alias"); + + ConfigurationEntry keyStoreEntry = new ConfigurationEntry(keyStoreId, KeyStore.class.getSimpleName(), attributes, Collections. emptySet(), + _store); + + _store.save(keyStoreEntry); + + ConfigurationEntry storeEntry = _store.getEntry(keyStoreId); + assertEquals("Unexpected key store configuration", keyStoreEntry, storeEntry); + assertEquals("Unexpected type", KeyStore.class.getSimpleName(), storeEntry.getType()); + assertEquals("Unexpected provider attributes", keyStoreEntry.getAttributes(), storeEntry.getAttributes()); + assertTrue("Unexpected provider children found", storeEntry.getChildrenIds().isEmpty()); + } + + public void testSaveGroupProvider() + { + UUID groupProviderId = UUID.randomUUID(); + Map attributes = new HashMap(); + attributes.put(GroupProvider.NAME, getName()); + + ConfigurationEntry groupProviderEntry = new ConfigurationEntry(groupProviderId, GroupProvider.class.getSimpleName(), attributes, + Collections. emptySet(), _store); + + _store.save(groupProviderEntry); + + ConfigurationEntry storeEntry = _store.getEntry(groupProviderId); + assertEquals("Unexpected group provider configuration", groupProviderEntry, storeEntry); + assertEquals("Unexpected type", GroupProvider.class.getSimpleName(), storeEntry.getType()); + assertEquals("Unexpected group provider attributes", groupProviderEntry.getAttributes(), storeEntry.getAttributes()); + assertTrue("Unexpected provider children found", storeEntry.getChildrenIds().isEmpty()); + } + + public void testSavePort() + { + UUID portId = UUID.randomUUID(); + Map attributes = new HashMap(); + Set tcpTransportSet = Collections.singleton(Transport.TCP.name()); + attributes.put(Port.PORT, 9999); + attributes.put(Port.TRANSPORTS, tcpTransportSet); + attributes.put(Port.TCP_NO_DELAY, true); + attributes.put(Port.RECEIVE_BUFFER_SIZE, 1); + attributes.put(Port.SEND_BUFFER_SIZE, 2); + attributes.put(Port.NEED_CLIENT_AUTH, true); + attributes.put(Port.WANT_CLIENT_AUTH, true); + + ConfigurationEntry portEntry = new ConfigurationEntry(portId, Port.class.getSimpleName(), attributes, Collections. emptySet(), _store); + + _store.save(portEntry); + + ConfigurationEntry storeEntry = _store.getEntry(portId); + assertEquals("Unexpected port configuration", portEntry, storeEntry); + assertEquals("Unexpected type", Port.class.getSimpleName(), storeEntry.getType()); + assertEquals("Unexpected port attributes", portEntry.getAttributes(), storeEntry.getAttributes()); + assertTrue("Unexpected port children found", storeEntry.getChildrenIds().isEmpty()); + } + + public void testMultipleSave() + { + UUID virtualHostId = UUID.randomUUID(); + Map virtualHostAttributes = new HashMap(); + virtualHostAttributes.put(VirtualHost.NAME, "test1"); + virtualHostAttributes.put(VirtualHost.CONFIG_PATH, "/path/to/phantom/virtualhost/config1"); + ConfigurationEntry hostEntry = new ConfigurationEntry(virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes, + Collections. emptySet(), _store); + + UUID keyStoreId = UUID.randomUUID(); + Map attributes = new HashMap(); + attributes.put(KeyStore.NAME, getName()); + attributes.put(KeyStore.PATH, "/path/to/truststore"); + attributes.put(KeyStore.PASSWORD, "my-secret-password"); + attributes.put(KeyStore.TYPE, "NON-JKS"); + attributes.put(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM, "NON-STANDARD"); + attributes.put(KeyStore.DESCRIPTION, "Description"); + attributes.put(KeyStore.CERTIFICATE_ALIAS, "Alias"); + + ConfigurationEntry keyStoreEntry = new ConfigurationEntry(keyStoreId, KeyStore.class.getSimpleName(), attributes, Collections. emptySet(), + _store); + + _store.save(hostEntry, keyStoreEntry); + + assertNotNull("Virtual host is not found", _store.getEntry(virtualHostId)); + assertNotNull("Key store is not found", _store.getEntry(keyStoreId)); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java new file mode 100644 index 0000000000..7c9f4889f8 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/store/JsonConfigurationEntryStoreTest.java @@ -0,0 +1,216 @@ +package org.apache.qpid.server.configuration.store; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.test.utils.TestFileUtils; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; + +public class JsonConfigurationEntryStoreTest extends ConfigurationEntryStoreTestCase +{ + private File _storeFile; + private ObjectMapper _objectMapper; + + @Override + public void setUp() throws Exception + { + _objectMapper = new ObjectMapper(); + _objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + super.setUp(); + } + + @Override + public void tearDown() throws Exception + { + _storeFile.delete(); + super.tearDown(); + } + + @Override + protected ConfigurationEntryStore createStore(UUID brokerId, Map brokerAttributes) throws Exception + { + _storeFile = createStoreFile(brokerId, brokerAttributes); + JsonConfigurationEntryStore store = new JsonConfigurationEntryStore(); + store.open(_storeFile.getAbsolutePath()); + return store; + } + + private File createStoreFile(UUID brokerId, Map brokerAttributes) throws IOException, + JsonGenerationException, JsonMappingException + { + Map brokerObjectMap = new HashMap(); + brokerObjectMap.put(Broker.ID, brokerId); + brokerObjectMap.put("@type", Broker.class.getSimpleName()); + brokerObjectMap.putAll(brokerAttributes); + + StringWriter sw = new StringWriter(); + _objectMapper.writeValue(sw, brokerObjectMap); + + String brokerJson = sw.toString(); + + return TestFileUtils.createTempFile(this, ".json", brokerJson); + } + + @Override + protected void addConfiguration(UUID id, String type, Map attributes) + { + ConfigurationEntryStore store = getStore(); + store.save(new ConfigurationEntry(id, type, attributes, Collections. emptySet(), store)); + } + + public void testAttributeIsResolvedFromSystemProperties() + { + String aclLocation = "path/to/acl/" + getTestName(); + setTestSystemProperty("my.test.property", aclLocation); + + ConfigurationEntryStore store = getStore(); + ConfigurationEntry brokerConfigEntry = store.getRootEntry(); + Map attributes = new HashMap(brokerConfigEntry.getAttributes()); + attributes.put(Broker.ACL_FILE, "${my.test.property}"); + ConfigurationEntry updatedBrokerEntry = new ConfigurationEntry(brokerConfigEntry.getId(), Broker.class.getSimpleName(), + attributes, brokerConfigEntry.getChildrenIds(), store); + store.save(updatedBrokerEntry); + + JsonConfigurationEntryStore store2 = new JsonConfigurationEntryStore(); + store2.open(_storeFile.getAbsolutePath()); + + assertEquals("Unresolved ACL value", aclLocation, store2.getRootEntry().getAttributes().get(Broker.ACL_FILE)); + } + + public void testOpenEmpty() + { + File file = TestFileUtils.createTempFile(this, ".json"); + JsonConfigurationEntryStore store = new JsonConfigurationEntryStore(); + store.open(file.getAbsolutePath()); + ConfigurationEntry root = store.getRootEntry(); + assertNotNull("Root entry is not found", root); + store.copyTo(file.getAbsolutePath()); + + JsonConfigurationEntryStore store2 = new JsonConfigurationEntryStore(); + store2.open(file.getAbsolutePath()); + ConfigurationEntry root2 = store.getRootEntry(); + assertEquals("Unexpected root entry", root.getId(), root2.getId()); + } + + public void testOpenNotEmpty() throws Exception + { + UUID brokerId = UUID.randomUUID(); + Map brokerAttributes = new HashMap(); + brokerAttributes.put(Broker.NAME, getTestName()); + File file = createStoreFile(brokerId, brokerAttributes); + + JsonConfigurationEntryStore store = new JsonConfigurationEntryStore(); + store.open(file.getAbsolutePath()); + ConfigurationEntry root = store.getRootEntry(); + assertNotNull("Root entry is not found", root); + assertEquals("Unexpected root entry", brokerId, root.getId()); + Map attributes = root.getAttributes(); + assertNotNull("Attributes not found", attributes); + assertEquals("Unexpected number of attriburtes", 1, attributes.size()); + assertEquals("Unexpected name attribute", getTestName(), attributes.get(Broker.NAME)); + } + + public void testOpenInMemoryEmpty() + { + JsonConfigurationEntryStore store = new JsonConfigurationEntryStore(); + store.open(JsonConfigurationEntryStore.IN_MEMORY); + + ConfigurationEntry root = store.getRootEntry(); + assertNotNull("Root entry is not found", root); + } + + public void testOpenWithInitialStoreLocation() throws Exception + { + UUID brokerId = UUID.randomUUID(); + Map brokerAttributes = new HashMap(); + brokerAttributes.put(Broker.NAME, getTestName()); + File initialStoreFile = createStoreFile(brokerId, brokerAttributes); + + File storeFile = TestFileUtils.createTempFile(this, ".json"); + JsonConfigurationEntryStore store = new JsonConfigurationEntryStore(); + store.open(storeFile.getAbsolutePath(), initialStoreFile.getAbsolutePath()); + + ConfigurationEntry root = store.getRootEntry(); + assertNotNull("Root entry is not found", root); + assertEquals("Unexpected root entry", brokerId, root.getId()); + Map attributes = root.getAttributes(); + assertNotNull("Attributes not found", attributes); + assertEquals("Unexpected number of attriburtes", 1, attributes.size()); + assertEquals("Unexpected name attribute", getTestName(), attributes.get(Broker.NAME)); + } + + public void testOpenInMemoryWithInitialStoreLocation() throws Exception + { + UUID brokerId = UUID.randomUUID(); + Map brokerAttributes = new HashMap(); + brokerAttributes.put(Broker.NAME, getTestName()); + File initialStoreFile = createStoreFile(brokerId, brokerAttributes); + + JsonConfigurationEntryStore store = new JsonConfigurationEntryStore(); + store.open(JsonConfigurationEntryStore.IN_MEMORY, initialStoreFile.getAbsolutePath()); + + ConfigurationEntry root = store.getRootEntry(); + assertNotNull("Root entry is not found", root); + assertEquals("Unexpected root entry", brokerId, root.getId()); + Map attributes = root.getAttributes(); + assertNotNull("Attributes not found", attributes); + assertEquals("Unexpected number of attriburtes", 1, attributes.size()); + assertEquals("Unexpected name attribute", getTestName(), attributes.get(Broker.NAME)); + } + + public void testOpenWithInitialStore() throws Exception + { + UUID brokerId = UUID.randomUUID(); + Map brokerAttributes = new HashMap(); + brokerAttributes.put(Broker.NAME, getTestName()); + File initialStoreFile = createStoreFile(brokerId, brokerAttributes); + + JsonConfigurationEntryStore initialStore = new JsonConfigurationEntryStore(); + initialStore.open(initialStoreFile.getAbsolutePath()); + + File storeFile = TestFileUtils.createTempFile(this, ".json"); + JsonConfigurationEntryStore store = new JsonConfigurationEntryStore(); + store.open(storeFile.getAbsolutePath(), initialStore); + + ConfigurationEntry root = store.getRootEntry(); + assertNotNull("Root entry is not found", root); + assertEquals("Unexpected root entry", brokerId, root.getId()); + Map attributes = root.getAttributes(); + assertNotNull("Attributes not found", attributes); + assertEquals("Unexpected number of attriburtes", 1, attributes.size()); + assertEquals("Unexpected name attribute", getTestName(), attributes.get(Broker.NAME)); + } + + public void testOpenInMemoryWithInitialStore() throws Exception + { + UUID brokerId = UUID.randomUUID(); + Map brokerAttributes = new HashMap(); + brokerAttributes.put(Broker.NAME, getTestName()); + File initialStoreFile = createStoreFile(brokerId, brokerAttributes); + + JsonConfigurationEntryStore initialStore = new JsonConfigurationEntryStore(); + initialStore.open(initialStoreFile.getAbsolutePath()); + + JsonConfigurationEntryStore store = new JsonConfigurationEntryStore(); + store.open(JsonConfigurationEntryStore.IN_MEMORY, initialStore); + + ConfigurationEntry root = store.getRootEntry(); + assertNotNull("Root entry is not found", root); + assertEquals("Unexpected root entry", brokerId, root.getId()); + Map attributes = root.getAttributes(); + assertNotNull("Attributes not found", attributes); + assertEquals("Unexpected number of attriburtes", 1, attributes.size()); + assertEquals("Unexpected name attribute", getTestName(), attributes.get(Broker.NAME)); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java new file mode 100644 index 0000000000..a67daac610 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java @@ -0,0 +1,341 @@ +package org.apache.qpid.server.configuration.store; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.any; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.BrokerOptions; +import org.apache.qpid.server.configuration.BrokerConfigurationStoreCreator; +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; + +public class ManagementModeStoreHandlerTest extends QpidTestCase +{ + private ManagementModeStoreHandler _handler; + private BrokerOptions _options; + private ConfigurationEntryStore _store; + private ConfigurationEntry _root; + private ConfigurationEntry _portEntry; + private UUID _rootId, _portEntryId; + + protected void setUp() throws Exception + { + super.setUp(); + _rootId = UUID.randomUUID(); + _portEntryId = UUID.randomUUID(); + _store = mock(ConfigurationEntryStore.class); + _root = mock(ConfigurationEntry.class); + _portEntry = mock(ConfigurationEntry.class); + when(_store.getRootEntry()).thenReturn(_root); + when(_root.getId()).thenReturn(_rootId); + when(_portEntry.getId()).thenReturn(_portEntryId); + when(_store.getEntry(_portEntryId)).thenReturn(_portEntry); + when(_store.getEntry(_rootId)).thenReturn(_root); + when(_root.getChildrenIds()).thenReturn(Collections.singleton(_portEntryId)); + when(_portEntry.getType()).thenReturn(Port.class.getSimpleName()); + _options = new BrokerOptions(); + _handler = new ManagementModeStoreHandler(_store, _options); + } + + public void testOpenString() + { + try + { + _handler.open(TMP_FOLDER + File.separator + getTestName()); + fail("Exception should be thrown on attempt to call open method on a handler"); + } + catch (IllegalStateException e) + { + // pass + } + } + + public void testOpenStringString() + { + try + { + _handler.open(TMP_FOLDER + File.separator + getTestName(), + BrokerConfigurationStoreCreator.DEFAULT_INITIAL_STORE_LOCATION); + fail("Exception should be thrown on attempt to call open method on a handler"); + } + catch (IllegalStateException e) + { + // pass + } + } + + public void testOpenStringConfigurationEntryStore() + { + try + { + _handler.open(TMP_FOLDER + File.separator + getTestName(), _store); + fail("Exception should be thrown on attempt to call open method on a handler"); + } + catch (IllegalStateException e) + { + // pass + } + } + + public void testGetRootEntryWithEmptyOptions() + { + ConfigurationEntry root = _handler.getRootEntry(); + assertEquals("Unexpected root id", _rootId, root.getId()); + assertEquals("Unexpected children", Collections.singleton(_portEntryId), root.getChildrenIds()); + } + + public void testGetRootEntryWithHttpPortOverriden() + { + _options.setManagementModeHttpPort(9090); + _handler = new ManagementModeStoreHandler(_store, _options); + ConfigurationEntry root = _handler.getRootEntry(); + assertEquals("Unexpected root id", _rootId, root.getId()); + Collection childrenIds = root.getChildrenIds(); + assertEquals("Unexpected children size", 2, childrenIds.size()); + assertTrue("Store port entry id is not found", childrenIds.contains(_portEntryId)); + } + + public void testGetRootEntryWithRmiPortOverriden() + { + _options.setManagementModeRmiPort(9090); + _handler = new ManagementModeStoreHandler(_store, _options); + ConfigurationEntry root = _handler.getRootEntry(); + assertEquals("Unexpected root id", _rootId, root.getId()); + Collection childrenIds = root.getChildrenIds(); + assertEquals("Unexpected children size", 3, childrenIds.size()); + assertTrue("Store port entry id is not found", childrenIds.contains(_portEntryId)); + } + + public void testGetRootEntryWithConnectorPortOverriden() + { + _options.setManagementModeConnectorPort(9090); + _handler = new ManagementModeStoreHandler(_store, _options); + ConfigurationEntry root = _handler.getRootEntry(); + assertEquals("Unexpected root id", _rootId, root.getId()); + Collection childrenIds = root.getChildrenIds(); + assertEquals("Unexpected children size", 2, childrenIds.size()); + assertTrue("Store port entry id is not found", childrenIds.contains(_portEntryId)); + } + + public void testGetRootEntryWithManagementPortsOverriden() + { + _options.setManagementModeHttpPort(1000); + _options.setManagementModeRmiPort(2000); + _options.setManagementModeConnectorPort(3000); + _handler = new ManagementModeStoreHandler(_store, _options); + ConfigurationEntry root = _handler.getRootEntry(); + assertEquals("Unexpected root id", _rootId, root.getId()); + Collection childrenIds = root.getChildrenIds(); + assertEquals("Unexpected children size", 4, childrenIds.size()); + assertTrue("Store port entry id is not found", childrenIds.contains(_portEntryId)); + } + + public void testGetEntryByRootId() + { + ConfigurationEntry root = _handler.getEntry(_rootId); + assertEquals("Unexpected root id", _rootId, root.getId()); + assertEquals("Unexpected children", Collections.singleton(_portEntryId), root.getChildrenIds()); + } + + public void testGetEntryByPortId() + { + ConfigurationEntry portEntry = _handler.getEntry(_portEntryId); + assertEquals("Unexpected entry id", _portEntryId, portEntry.getId()); + assertTrue("Unexpected children", portEntry.getChildrenIds().isEmpty()); + assertEquals("Unexpected state", State.QUIESCED, portEntry.getAttributes().get(Port.STATE)); + } + + public void testGetEntryByCLIConnectorPortId() + { + _options.setManagementModeConnectorPort(9090); + _handler = new ManagementModeStoreHandler(_store, _options); + + UUID optionsPort = getOptionsPortId(); + ConfigurationEntry portEntry = _handler.getEntry(optionsPort); + assertCLIPortEntry(portEntry, optionsPort, Protocol.JMX_RMI); + } + + public void testGetEntryByCLIHttpPortId() + { + _options.setManagementModeHttpPort(9090); + _handler = new ManagementModeStoreHandler(_store, _options); + + UUID optionsPort = getOptionsPortId(); + ConfigurationEntry portEntry = _handler.getEntry(optionsPort); + assertCLIPortEntry(portEntry, optionsPort, Protocol.HTTP); + } + + public void testHttpPortEntryIsQuiesced() + { + Map attributes = new HashMap(); + attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.HTTP)); + when(_portEntry.getAttributes()).thenReturn(attributes); + _options.setManagementModeHttpPort(9090); + _handler = new ManagementModeStoreHandler(_store, _options); + + ConfigurationEntry portEntry = _handler.getEntry(_portEntryId); + assertEquals("Unexpected state", State.QUIESCED, portEntry.getAttributes().get(Port.STATE)); + } + + public void testRmiPortEntryIsQuiesced() + { + Map attributes = new HashMap(); + attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.RMI)); + when(_portEntry.getAttributes()).thenReturn(attributes); + _options.setManagementModeRmiPort(9090); + _handler = new ManagementModeStoreHandler(_store, _options); + + ConfigurationEntry portEntry = _handler.getEntry(_portEntryId); + assertEquals("Unexpected state", State.QUIESCED, portEntry.getAttributes().get(Port.STATE)); + } + + public void testConnectorPortEntryIsQuiesced() + { + Map attributes = new HashMap(); + attributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.JMX_RMI)); + when(_portEntry.getAttributes()).thenReturn(attributes); + _options.setManagementModeRmiPort(9090); + _handler = new ManagementModeStoreHandler(_store, _options); + + ConfigurationEntry portEntry = _handler.getEntry(_portEntryId); + assertEquals("Unexpected state", State.QUIESCED, portEntry.getAttributes().get(Port.STATE)); + } + + public void testVirtualHostEntryIsQuiesced() + { + UUID virtualHostId = UUID.randomUUID(); + ConfigurationEntry virtualHost = mock(ConfigurationEntry.class); + when(virtualHost.getId()).thenReturn(virtualHostId); + when(virtualHost.getType()).thenReturn(VirtualHost.class.getSimpleName()); + Map attributes = new HashMap(); + attributes.put(VirtualHost.CONFIG_PATH, "/path/to/host.xml"); + when(virtualHost.getAttributes()).thenReturn(attributes); + when(_store.getEntry(virtualHostId)).thenReturn(virtualHost); + when(_root.getChildrenIds()).thenReturn(new HashSet(Arrays.asList(_portEntryId, virtualHostId))); + + _handler = new ManagementModeStoreHandler(_store, _options); + + ConfigurationEntry hostEntry = _handler.getEntry(virtualHostId); + Map hostAttributes = hostEntry.getAttributes(); + assertEquals("Unexpected state", State.QUIESCED, hostAttributes.get(VirtualHost.STATE)); + hostAttributes.remove(VirtualHost.STATE); + assertEquals("Unexpected attributes", attributes, hostAttributes); + } + + @SuppressWarnings("unchecked") + private void assertCLIPortEntry(ConfigurationEntry portEntry, UUID optionsPort, Protocol protocol) + { + assertEquals("Unexpected entry id", optionsPort, portEntry.getId()); + assertTrue("Unexpected children", portEntry.getChildrenIds().isEmpty()); + Map attributes = portEntry.getAttributes(); + assertEquals("Unexpected name", "MANAGEMENT-MODE-PORT-" + protocol.name(), attributes.get(Port.NAME)); + assertEquals("Unexpected protocol", Collections.singleton(protocol), new HashSet( + (Collection) attributes.get(Port.PROTOCOLS))); + } + + public void testSavePort() + { + _options.setManagementModeHttpPort(1000); + _options.setManagementModeRmiPort(2000); + _options.setManagementModeConnectorPort(3000); + _handler = new ManagementModeStoreHandler(_store, _options); + + Map attributes = new HashMap(); + attributes.put(Port.NAME, "TEST"); + ConfigurationEntry configurationEntry = new ConfigurationEntry(_portEntryId, Port.class.getSimpleName(), attributes, + Collections. emptySet(), null); + _handler.save(configurationEntry); + verify(_store).save(any(ConfigurationEntry.class)); + } + + public void testSaveRoot() + { + _options.setManagementModeHttpPort(1000); + _options.setManagementModeRmiPort(2000); + _options.setManagementModeConnectorPort(3000); + _handler = new ManagementModeStoreHandler(_store, _options); + + ConfigurationEntry root = _handler.getRootEntry(); + Map attributes = new HashMap(); + attributes.put(Broker.NAME, "TEST"); + ConfigurationEntry configurationEntry = new ConfigurationEntry(_rootId, Broker.class.getSimpleName(), attributes, + root.getChildrenIds(), null); + _handler.save(configurationEntry); + verify(_store).save(any(ConfigurationEntry.class)); + } + + public void testSaveCLIHttpPort() + { + _options.setManagementModeHttpPort(1000); + _handler = new ManagementModeStoreHandler(_store, _options); + + UUID portId = getOptionsPortId(); + Map attributes = new HashMap(); + attributes.put(Port.NAME, "TEST"); + ConfigurationEntry configurationEntry = new ConfigurationEntry(portId, Port.class.getSimpleName(), attributes, + Collections. emptySet(), null); + try + { + _handler.save(configurationEntry); + fail("Exception should be thrown on trying to save CLI port"); + } + catch (IllegalConfigurationException e) + { + // pass + } + } + + public void testRemove() + { + _options.setManagementModeHttpPort(1000); + _handler = new ManagementModeStoreHandler(_store, _options); + + _handler.remove(_portEntryId); + verify(_store).remove(_portEntryId); + } + + public void testRemoveCLIPort() + { + _options.setManagementModeHttpPort(1000); + _handler = new ManagementModeStoreHandler(_store, _options); + UUID portId = getOptionsPortId(); + try + { + _handler.remove(portId); + fail("Exception should be thrown on trying to remove CLI port"); + } + catch (IllegalConfigurationException e) + { + // pass + } + } + + private UUID getOptionsPortId() + { + ConfigurationEntry root = _handler.getRootEntry(); + assertEquals("Unexpected root id", _rootId, root.getId()); + Collection childrenIds = root.getChildrenIds(); + + childrenIds.remove(_portEntryId); + UUID optionsPort = childrenIds.iterator().next(); + return optionsPort; + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java new file mode 100644 index 0000000000..a77a0e9fcc --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java @@ -0,0 +1,83 @@ +package org.apache.qpid.server.configuration.store; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.when; + +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; + +public class StoreConfigurationChangeListenerTest extends QpidTestCase +{ + private ConfigurationEntryStore _store; + private StoreConfigurationChangeListener _listener; + + protected void setUp() throws Exception + { + super.setUp(); + _store = mock(ConfigurationEntryStore.class); + _listener = new StoreConfigurationChangeListener(_store); + } + + public void testStateChanged() + { + notifyBrokerStarted(); + UUID id = UUID.randomUUID(); + ConfiguredObject object = mock(VirtualHost.class); + when(object.getId()).thenReturn(id); + _listener.stateChanged(object, State.ACTIVE, State.DELETED); + verify(_store).remove(id); + } + + public void testChildAdded() + { + notifyBrokerStarted(); + Broker broker = mock(Broker.class); + VirtualHost child = mock(VirtualHost.class); + _listener.childAdded(broker, child); + verify(_store).save(any(ConfigurationEntry.class), any(ConfigurationEntry.class)); + } + + public void testChildRemoved() + { + notifyBrokerStarted(); + Broker broker = mock(Broker.class); + VirtualHost child = mock(VirtualHost.class); + _listener.childRemoved(broker, child); + verify(_store).save(any(ConfigurationEntry.class)); + } + + public void testAttributeSet() + { + notifyBrokerStarted(); + Broker broker = mock(Broker.class); + _listener.attributeSet(broker, Broker.FLOW_CONTROL_SIZE_BYTES, null, 1); + verify(_store).save(any(ConfigurationEntry.class)); + } + + public void testChildAddedForVirtualHost() + { + notifyBrokerStarted(); + + VirtualHost object = mock(VirtualHost.class); + Queue queue = mock(Queue.class); + _listener.childAdded(object, queue); + verifyNoMoreInteractions(_store); + } + + private void notifyBrokerStarted() + { + Broker broker = mock(Broker.class); + _listener.stateChanged(broker, State.INITIALISING, State.ACTIVE); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/updater/TaskExecutorTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/updater/TaskExecutorTest.java new file mode 100644 index 0000000000..cd6302d55b --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/updater/TaskExecutorTest.java @@ -0,0 +1,296 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.updater; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import javax.security.auth.Subject; + +import junit.framework.TestCase; + +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.NullRootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.TestLogActor; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.security.SecurityManager; + +public class TaskExecutorTest extends TestCase +{ + private TaskExecutor _executor; + + protected void setUp() throws Exception + { + super.setUp(); + _executor = new TaskExecutor(); + } + + protected void tearDown() throws Exception + { + try + { + _executor.stopImmediately(); + } + finally + { + super.tearDown(); + } + } + + public void testGetState() + { + assertEquals("Unxpected initial state", State.INITIALISING, _executor.getState()); + } + + public void testStart() + { + _executor.start(); + assertEquals("Unxpected started state", State.ACTIVE, _executor.getState()); + } + + public void testStopImmediately() throws Exception + { + _executor.start(); + final CountDownLatch submitLatch = new CountDownLatch(2); + final CountDownLatch waitForCallLatch = new CountDownLatch(1); + final BlockingQueue submitExceptions = new LinkedBlockingQueue(); + + Runnable runnable = new Runnable() + { + @Override + public void run() + { + try + { + Future f = _executor.submit(new NeverEndingCallable(waitForCallLatch)); + submitLatch.countDown(); + f.get(); + } + catch (Exception e) + { + if (e instanceof ExecutionException) + { + e = (Exception) e.getCause(); + } + submitExceptions.add(e); + } + } + }; + new Thread(runnable).start(); + new Thread(runnable).start(); + assertTrue("Tasks have not been submitted", submitLatch.await(1000, TimeUnit.MILLISECONDS)); + assertTrue("The first task has not been triggered", waitForCallLatch.await(1000, TimeUnit.MILLISECONDS)); + + _executor.stopImmediately(); + assertEquals("Unxpected stopped state", State.STOPPED, _executor.getState()); + + Exception e = submitExceptions.poll(1000l, TimeUnit.MILLISECONDS); + assertNotNull("The task execution was not interrupted or cancelled", e); + Exception e2 = submitExceptions.poll(1000l, TimeUnit.MILLISECONDS); + assertNotNull("The task execution was not interrupted or cancelled", e2); + + assertTrue("One of the exceptions should be CancellationException:", e2 instanceof CancellationException + || e instanceof CancellationException); + assertTrue("One of the exceptions should be InterruptedException:", e2 instanceof InterruptedException + || e instanceof InterruptedException); + } + + public void testStop() + { + _executor.start(); + _executor.stop(); + assertEquals("Unxpected stopped state", State.STOPPED, _executor.getState()); + } + + public void testSubmitAndWait() throws Exception + { + _executor.start(); + Object result = _executor.submitAndWait(new Callable() + { + @Override + public String call() throws Exception + { + return "DONE"; + } + }); + assertEquals("Unexpected task execution result", "DONE", result); + } + + public void testSubmitAndWaitInNotAuthorizedContext() + { + _executor.start(); + Object subject = _executor.submitAndWait(new SubjectRetriever()); + assertNull("Subject must be null", subject); + } + + public void testSubmitAndWaitInAuthorizedContext() + { + _executor.start(); + Subject subject = new Subject(); + Object result = Subject.doAs(subject, new PrivilegedAction() + { + @Override + public Object run() + { + return _executor.submitAndWait(new SubjectRetriever()); + } + }); + assertEquals("Unexpected subject", subject, result); + } + + public void testSubmitAndWaitInAuthorizedContextWithNullSubject() + { + _executor.start(); + Object result = Subject.doAs(null, new PrivilegedAction() + { + @Override + public Object run() + { + return _executor.submitAndWait(new SubjectRetriever()); + } + }); + assertEquals("Unexpected subject", null, result); + } + + public void testSubmitAndWaitReThrowsOriginalRuntimeException() + { + final RuntimeException exception = new RuntimeException(); + _executor.start(); + try + { + _executor.submitAndWait(new Callable() + { + + @Override + public Void call() throws Exception + { + throw exception; + } + }); + fail("Exception is expected"); + } + catch (Exception e) + { + assertEquals("Unexpected exception", exception, e); + } + } + + public void testSubmitAndWaitPassesOriginalCheckedException() + { + final Exception exception = new Exception(); + _executor.start(); + try + { + _executor.submitAndWait(new Callable() + { + + @Override + public Void call() throws Exception + { + throw exception; + } + }); + fail("Exception is expected"); + } + catch (Exception e) + { + assertEquals("Unexpected exception", exception, e.getCause()); + } + } + + public void testSubmitAndWaitCurrentActorAndSecurityManagerSubjectAreRespected() throws Exception + { + _executor.start(); + LogActor actor = new TestLogActor(new NullRootMessageLogger()); + Subject subject = new Subject(); + Subject currentSecurityManagerSubject = SecurityManager.getThreadSubject(); + final AtomicReference taskLogActor = new AtomicReference(); + final AtomicReference taskSubject = new AtomicReference(); + try + { + CurrentActor.set(actor); + SecurityManager.setThreadSubject(subject); + _executor.submitAndWait(new Callable() + { + @Override + public Void call() throws Exception + { + taskLogActor.set(CurrentActor.get()); + taskSubject.set(SecurityManager.getThreadSubject()); + return null; + } + }); + } + finally + { + SecurityManager.setThreadSubject(currentSecurityManagerSubject); + CurrentActor.remove(); + } + assertEquals("Unexpected task log actor", actor, taskLogActor.get()); + assertEquals("Unexpected security manager subject", subject, taskSubject.get()); + } + + private class SubjectRetriever implements Callable + { + @Override + public Subject call() throws Exception + { + return Subject.getSubject(AccessController.getContext()); + } + } + + private class NeverEndingCallable implements Callable + { + private CountDownLatch _waitLatch; + + public NeverEndingCallable(CountDownLatch waitLatch) + { + super(); + _waitLatch = waitLatch; + } + + @Override + public Void call() throws Exception + { + if (_waitLatch != null) + { + _waitLatch.countDown(); + } + + // wait forever + synchronized (this) + { + this.wait(); + } + return null; + } + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java index 4befd26ece..0bb698a46c 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java +++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java @@ -29,7 +29,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; import org.apache.log4j.Logger; @@ -54,25 +53,56 @@ import org.apache.qpid.server.queue.IncomingMessage; import org.apache.qpid.server.queue.MockStoredMessage; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.queue.SimpleAMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; -public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase +public class AbstractHeadersExchangeTestBase extends QpidTestCase { private static final Logger _log = Logger.getLogger(AbstractHeadersExchangeTestBase.class); private final HeadersExchange exchange = new HeadersExchange(); - protected final Set queues = new HashSet(); - + private final Set queues = new HashSet(); + private VirtualHost _virtualHost; private int count; + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _virtualHost = BrokerTestHelper.createVirtualHost(getClass().getName()); + } + + @Override + public void tearDown() throws Exception + { + try + { + if (_virtualHost != null) + { + _virtualHost.close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + } + public void testDoNothing() { // this is here only to make junit under Eclipse happy } + public VirtualHost getVirtualHost() + { + return _virtualHost; + } + protected TestQueue bindDefault(String... bindings) throws AMQException { String queueName = "Queue" + (++count); @@ -83,7 +113,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase protected void unbind(TestQueue queue, String... bindings) throws AMQException { String queueName = queue.getName(); - exchange.onUnbind(new Binding(null, null, queueName, queue, exchange, getHeadersMap(bindings))); + exchange.onUnbind(new Binding(null, queueName, queue, exchange, getHeadersMap(bindings))); } protected int getCount() @@ -93,9 +123,9 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase private TestQueue bind(String key, String queueName, Map args) throws AMQException { - TestQueue queue = new TestQueue(new AMQShortString(queueName)); + TestQueue queue = new TestQueue(new AMQShortString(queueName), _virtualHost); queues.add(queue); - exchange.onBind(new Binding(null, null, key, queue, exchange, args)); + exchange.onBind(new Binding(null, key, queue, exchange, args)); return queue; } @@ -274,10 +304,10 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase return getNameShortString().toString(); } - public TestQueue(AMQShortString name) throws AMQException + public TestQueue(AMQShortString name, VirtualHost host) throws AMQException { - super(UUIDGenerator.generateRandomUUID(), name, false, new AMQShortString("test"), true, false,ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"), Collections.EMPTY_MAP); - ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test").getQueueRegistry().registerQueue(this); + super(UUIDGenerator.generateRandomUUID(), name, false, new AMQShortString("test"), true, false, host, Collections.EMPTY_MAP); + host.getQueueRegistry().registerQueue(this); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java new file mode 100644 index 0000000000..341ab1b372 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java @@ -0,0 +1,226 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.exchange; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; + +@SuppressWarnings("rawtypes") +public class DefaultExchangeFactoryTest extends QpidTestCase +{ + private DirectExchangeType _directExchangeType; + private TopicExchangeType _topicExchangeType; + private FanoutExchangeType _fanoutExchangeType; + private HeadersExchangeType _headersExchangeType; + + private List _stubbedExchangeTypes; + + protected void setUp() throws Exception + { + super.setUp(); + + _directExchangeType = new DirectExchangeType(); + _topicExchangeType = new TopicExchangeType(); + _fanoutExchangeType = new FanoutExchangeType(); + _headersExchangeType = new HeadersExchangeType(); + _stubbedExchangeTypes = new ArrayList(); + } + + public void testCreateDefaultExchangeFactory() + { + _stubbedExchangeTypes.add(_directExchangeType); + _stubbedExchangeTypes.add(_topicExchangeType); + _stubbedExchangeTypes.add(_fanoutExchangeType); + _stubbedExchangeTypes.add(_headersExchangeType); + + DefaultExchangeFactory factory = new TestExchangeFactory(); + + Collection> registeredTypes = factory.getRegisteredTypes(); + assertEquals("Unexpected number of exchange types", _stubbedExchangeTypes.size(), registeredTypes.size()); + assertTrue("Direct exchange type is not found", registeredTypes.contains(_directExchangeType)); + assertTrue("Fanout exchange type is not found", registeredTypes.contains(_fanoutExchangeType)); + assertTrue("Topic exchange type is not found", registeredTypes.contains(_topicExchangeType)); + assertTrue("Headers exchange type is not found", registeredTypes.contains(_headersExchangeType)); + } + + public void testCreateDefaultExchangeFactoryWithoutAllBaseExchangeTypes() + { + try + { + new TestExchangeFactory(); + fail("Cannot create factory without all base classes"); + } + catch (IllegalStateException e) + { + // pass + } + } + + public void testCreateDefaultExchangeFactoryWithoutDireactExchangeType() + { + _stubbedExchangeTypes.add(_topicExchangeType); + _stubbedExchangeTypes.add(_fanoutExchangeType); + _stubbedExchangeTypes.add(_headersExchangeType); + + try + { + new TestExchangeFactory(); + fail("Cannot create factory without all base classes"); + } + catch (IllegalStateException e) + { + assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _directExchangeType.getName(), e.getMessage()); + } + } + + public void testCreateDefaultExchangeFactoryWithoutTopicExchangeType() + { + _stubbedExchangeTypes.add(_directExchangeType); + _stubbedExchangeTypes.add(_fanoutExchangeType); + _stubbedExchangeTypes.add(_headersExchangeType); + + try + { + new TestExchangeFactory(); + fail("Cannot create factory without all base classes"); + } + catch (IllegalStateException e) + { + assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _topicExchangeType.getName(), e.getMessage()); + } + } + + public void testCreateDefaultExchangeFactoryWithoutFanoutExchangeType() + { + _stubbedExchangeTypes.add(_directExchangeType); + _stubbedExchangeTypes.add(_topicExchangeType); + _stubbedExchangeTypes.add(_headersExchangeType); + + try + { + new TestExchangeFactory(); + fail("Cannot create factory without all base classes"); + } + catch (IllegalStateException e) + { + assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _fanoutExchangeType.getName(), e.getMessage()); + } + } + + public void testCreateDefaultExchangeFactoryWithoutHeadersExchangeType() + { + _stubbedExchangeTypes.add(_directExchangeType); + _stubbedExchangeTypes.add(_topicExchangeType); + _stubbedExchangeTypes.add(_fanoutExchangeType); + + try + { + new TestExchangeFactory(); + fail("Cannot create factory without all base classes"); + } + catch (IllegalStateException e) + { + assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _headersExchangeType.getName(), e.getMessage()); + } + } + + public void testCreateDefaultExchangeFactoryWithDuplicateExchangeTypeName() + { + _stubbedExchangeTypes.add(_directExchangeType); + _stubbedExchangeTypes.add(_directExchangeType); + + try + { + new TestExchangeFactory(); + fail("Cannot create factory with duplicate exchange type names"); + } + catch (IllegalStateException e) + { + assertTrue( "Unexpected exception message", e.getMessage().contains("ExchangeType with type name '" + + _directExchangeType.getName() + "' is already registered using class '" + + DirectExchangeType.class.getName())); + } + } + + public void testCreateDefaultExchangeFactoryWithCustomExchangeType() + { + ExchangeType customeExchangeType = new ExchangeType() + { + @Override + public AMQShortString getName() + { + return new AMQShortString("my-custom-exchange"); + } + + @Override + public Exchange newInstance(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, + boolean autoDelete) throws AMQException + { + return null; + } + + @Override + public AMQShortString getDefaultExchangeName() + { + return null; + } + }; + + _stubbedExchangeTypes.add(customeExchangeType); + _stubbedExchangeTypes.add(_directExchangeType); + _stubbedExchangeTypes.add(_topicExchangeType); + _stubbedExchangeTypes.add(_fanoutExchangeType); + _stubbedExchangeTypes.add(_headersExchangeType); + + DefaultExchangeFactory factory = new TestExchangeFactory(); + + Collection> registeredTypes = factory.getRegisteredTypes(); + assertEquals("Unexpected number of exchange types", _stubbedExchangeTypes.size(), registeredTypes.size()); + assertTrue("Direct exchange type is not found", registeredTypes.contains(_directExchangeType)); + assertTrue("Fanout exchange type is not found", registeredTypes.contains(_fanoutExchangeType)); + assertTrue("Topic exchange type is not found", registeredTypes.contains(_topicExchangeType)); + assertTrue("Headers exchange type is not found", registeredTypes.contains(_headersExchangeType)); + assertTrue("Custom exchange type is not found", registeredTypes.contains(customeExchangeType)); + } + + private final class TestExchangeFactory extends DefaultExchangeFactory + { + private TestExchangeFactory() + { + super(null); + } + + @Override + protected Iterable loadExchangeTypes() + { + return _stubbedExchangeTypes; + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java index 3988edcb3c..833df34fd8 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java @@ -160,7 +160,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -171,7 +171,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); matchHeaders.setString("B", "Value of B"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -181,7 +181,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Altered value of A"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertFalse(new HeadersBinding(b).matches(matchHeaders)); } @@ -192,7 +192,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -204,7 +204,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertFalse(new HeadersBinding(b).matches(matchHeaders)); } @@ -217,7 +217,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); matchHeaders.setString("B", "Value of B"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -231,7 +231,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -245,7 +245,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Altered value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertFalse(new HeadersBinding(b).matches(matchHeaders)); } @@ -256,7 +256,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -268,7 +268,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -281,7 +281,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); matchHeaders.setString("B", "Value of B"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -295,7 +295,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -309,7 +309,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Altered value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -323,7 +323,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Altered value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); assertFalse(new HeadersBinding(b).matches(matchHeaders)); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java index 326d36df05..bd6a02d69b 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java @@ -23,8 +23,7 @@ package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.util.BrokerTestHelper; public class HeadersExchangeTest extends AbstractHeadersExchangeTestBase { @@ -34,10 +33,15 @@ public class HeadersExchangeTest extends AbstractHeadersExchangeTestBase public void setUp() throws Exception { super.setUp(); - // Just use the first vhost. - VirtualHost - virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next(); - _protocolSession = new InternalTestProtocolSession(virtualHost); + BrokerTestHelper.setUp(); + _protocolSession = new InternalTestProtocolSession(getVirtualHost(), BrokerTestHelper.createBrokerMock()); + } + + @Override + public void tearDown() throws Exception + { + BrokerTestHelper.tearDown(); + super.tearDown(); } public void testSimple() throws AMQException diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java index 92274afece..f1bf632235 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java @@ -31,42 +31,55 @@ import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.IncomingMessage; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; -public class TopicExchangeTest extends InternalBrokerBaseCase +public class TopicExchangeTest extends QpidTestCase { private TopicExchange _exchange; - private VirtualHost _vhost; private MessageStore _store; - private InternalTestProtocolSession _protocolSession; - @Override public void setUp() throws Exception { super.setUp(); + BrokerTestHelper.setUp(); _exchange = new TopicExchange(); - _vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next(); + _vhost = BrokerTestHelper.createVirtualHost(getName()); _store = new MemoryMessageStore(); - _protocolSession = new InternalTestProtocolSession(_vhost); + } + + @Override + public void tearDown() throws Exception + { + try + { + if (_vhost != null) + { + _vhost.close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } } public void testNoRoute() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a*#b", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.*.#.b",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.*.#.b",queue, _exchange, null)); IncomingMessage message = createMessage("a.b"); @@ -78,7 +91,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testDirectMatch() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "ab", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.b",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.b",queue, _exchange, null)); IncomingMessage message = createMessage("a.b"); @@ -105,7 +118,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testStarMatch() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a*", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.*",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.*",queue, _exchange, null)); IncomingMessage message = createMessage("a.b"); @@ -144,7 +157,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testHashMatch() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.#",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.#",queue, _exchange, null)); IncomingMessage message = createMessage("a.b.c"); @@ -207,7 +220,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testMidHash() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.*.#.b",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.*.#.b",queue, _exchange, null)); IncomingMessage message = createMessage("a.c.d.b"); @@ -237,7 +250,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testMatchafterHash() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.*.#.b.c",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.*.#.b.c",queue, _exchange, null)); IncomingMessage message = createMessage("a.c.b.b"); @@ -283,7 +296,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testHashAfterHash() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.*.#.b.c.#.d",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.*.#.b.c.#.d",queue, _exchange, null)); IncomingMessage message = createMessage("a.c.b.b.c"); @@ -310,7 +323,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testHashHash() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.#.*.#.d",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.#.*.#.d",queue, _exchange, null)); IncomingMessage message = createMessage("a.c.b.b.c"); @@ -336,7 +349,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testSubMatchFails() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.b.c.d",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.b.c.d",queue, _exchange, null)); IncomingMessage message = createMessage("a.b.c"); @@ -366,7 +379,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testMoreRouting() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.b",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.b",queue, _exchange, null)); IncomingMessage message = createMessage("a.b.c"); @@ -381,7 +394,7 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testMoreQueue() throws AMQException { AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null, null, "a.b",queue, _exchange, null)); + _exchange.registerQueue(new Binding(null, "a.b",queue, _exchange, null)); IncomingMessage message = createMessage("a"); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/UnitTestMessageLogger.java b/java/broker/src/test/java/org/apache/qpid/server/logging/UnitTestMessageLogger.java index fabbe8640e..be31f3d039 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/UnitTestMessageLogger.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/UnitTestMessageLogger.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.logging; -import org.apache.qpid.server.configuration.ServerConfiguration; import java.util.LinkedList; import java.util.List; @@ -34,9 +33,9 @@ public class UnitTestMessageLogger extends AbstractRootMessageLogger } - public UnitTestMessageLogger(ServerConfiguration config) + public UnitTestMessageLogger(boolean statusUpdatesEnabled) { - super(config); + super(statusUpdatesEnabled); } public void rawMessage(String message, String logHierarchy) diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java index f739d3fcb9..e2472dbf01 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java @@ -20,9 +20,8 @@ */ package org.apache.qpid.server.logging.actors; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.AMQException; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.util.BrokerTestHelper; import java.util.List; @@ -38,24 +37,17 @@ import java.util.List; public class AMQPChannelActorTest extends BaseConnectionActorTestCase { - @Override - public void configure() + public void setUp() { - // Prevent defaulting Logging to ON + // do nothing } - - @Override - public void createBroker() throws Exception + private void setUpNow() throws Exception { - //prevent auto-broker startup - } + super.setUp(); + AMQChannel channel = BrokerTestHelper.createChannel(1, getSession()); - private void startBrokerNow() throws Exception - { - super.createBroker(); - - _amqpActor = new AMQPChannelActor(getChannel(), _rootLogger); + setAmqpActor(new AMQPChannelActor(channel, getRootLogger())); } @@ -68,13 +60,11 @@ public class AMQPChannelActorTest extends BaseConnectionActorTestCase */ public void testChannel() throws Exception { - getConfigXml().setProperty("status-updates", "ON"); - - startBrokerNow(); + setUpNow(); - final String message = sendTestLogMessage(_amqpActor); + final String message = sendTestLogMessage(getAmqpActor()); - List logs = _rawLogger.getLogMessages(); + List logs = getRawLogger().getLogMessages(); assertEquals("Message log size not as expected.", 1, logs.size()); @@ -95,128 +85,22 @@ public class AMQPChannelActorTest extends BaseConnectionActorTestCase // Verify that the logged message contains the 'ch:1' marker assertTrue("Message was not logged as part of channel 1" + logs.get(0), logs.get(0).toString().contains("/ch:1")); - - } - - /** - * Test that if logging is configured to be off in the configuration that - * no logging is presented - * @throws ConfigurationException - * @throws AMQException - */ - public void testChannelLoggingOFF() throws Exception, AMQException - { - getConfigXml().setProperty("status-updates", "OFF"); - - // Start the broker now. - startBrokerNow(); - - sendTestLogMessage(_amqpActor); - - List logs = _rawLogger.getLogMessages(); - - assertEquals("Message log size not as expected.", 0, logs.size()); - - } - - /** - * Test that if logging is configured to be off in the configuration that - * no logging is presented - * @throws ConfigurationException - * @throws AMQException - */ - public void testChannelLoggingOfF() throws Exception, AMQException - { - getConfigXml().setProperty("status-updates", "OfF"); - - startBrokerNow(); - - sendTestLogMessage(_amqpActor); - - List logs = _rawLogger.getLogMessages(); - - assertEquals("Message log size not as expected.", 0, logs.size()); - - } - - /** - * Test that if logging is configured to be off in the configuration that - * no logging is presented - * @throws ConfigurationException - * @throws AMQException - */ - public void testChannelLoggingOff() throws Exception, AMQException - { - getConfigXml().setProperty("status-updates", "Off"); - - startBrokerNow(); - - sendTestLogMessage(_amqpActor); - - List logs = _rawLogger.getLogMessages(); - - assertEquals("Message log size not as expected.", 0, logs.size()); - } /** - * Test that if logging is configured to be off in the configuration that + * Test that if logging is configured to be off via system property that * no logging is presented - * @throws ConfigurationException - * @throws AMQException */ - public void testChannelLoggingofF() throws Exception, AMQException + public void testChannelLoggingOFF() throws Exception { - getConfigXml().setProperty("status-updates", "ofF"); + setStatusUpdatesEnabled(false); - startBrokerNow(); + setUpNow(); - sendTestLogMessage(_amqpActor); + sendTestLogMessage(getAmqpActor()); - List logs = _rawLogger.getLogMessages(); + List logs = getRawLogger().getLogMessages(); assertEquals("Message log size not as expected.", 0, logs.size()); - } - - /** - * Test that if logging is configured to be off in the configuration that - * no logging is presented - * @throws ConfigurationException - * @throws AMQException - */ - public void testChannelLoggingoff() throws Exception, AMQException - { - getConfigXml().setProperty("status-updates", "off"); - - startBrokerNow(); - - sendTestLogMessage(_amqpActor); - - List logs = _rawLogger.getLogMessages(); - - assertEquals("Message log size not as expected.", 0, logs.size()); - - } - - /** - * Test that if logging is configured to be off in the configuration that - * no logging is presented - * @throws ConfigurationException - * @throws AMQException - */ - public void testChannelLoggingoFf() throws Exception, AMQException - { - getConfigXml().setProperty("status-updates", "oFf"); - - startBrokerNow(); - - sendTestLogMessage(_amqpActor); - - List logs = _rawLogger.getLogMessages(); - - assertEquals("Message log size not as expected.", 0, logs.size()); - - } - } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java index 4eda9e9da1..d1cf256563 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPConnectionActorTest.java @@ -38,16 +38,9 @@ import java.util.List; public class AMQPConnectionActorTest extends BaseConnectionActorTestCase { @Override - public void configure() + public void setUp() { - // Prevent defaulting Logging to ON - } - - - @Override - public void createBroker() - { - //Prevent auto-broker startup + //Prevent logger creation } /** @@ -60,13 +53,11 @@ public class AMQPConnectionActorTest extends BaseConnectionActorTestCase */ public void testConnection() throws Exception { - getConfigXml().setProperty("status-updates", "ON"); - - super.createBroker(); + super.setUp(); final String message = sendLogMessage(); - List logs = _rawLogger.getLogMessages(); + List logs = getRawLogger().getLogMessages(); assertEquals("Message log size not as expected.", 1, logs.size()); @@ -90,14 +81,13 @@ public class AMQPConnectionActorTest extends BaseConnectionActorTestCase public void testConnectionLoggingOff() throws Exception, AMQException { - getConfigXml().setProperty("status-updates", "OFF"); + setStatusUpdatesEnabled(false); - // Start the broker now. - super.createBroker(); + super.setUp(); sendLogMessage(); - List logs = _rawLogger.getLogMessages(); + List logs = getRawLogger().getLogMessages(); assertEquals("Message log size not as expected.", 0, logs.size()); @@ -107,7 +97,7 @@ public class AMQPConnectionActorTest extends BaseConnectionActorTestCase { final String message = "test logging"; - _amqpActor.message(new LogSubject() + getAmqpActor().message(new LogSubject() { public String toLogString() { diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AbstractManagementActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AbstractManagementActorTest.java new file mode 100644 index 0000000000..bf38bb64bf --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AbstractManagementActorTest.java @@ -0,0 +1,86 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.logging.actors; + +import java.security.Principal; +import java.security.PrivilegedAction; +import java.util.Collections; + +import javax.security.auth.Subject; + +import org.apache.qpid.server.logging.NullRootMessageLogger; +import org.apache.qpid.server.security.auth.TestPrincipalUtils; +import org.apache.qpid.test.utils.QpidTestCase; + +public class AbstractManagementActorTest extends QpidTestCase +{ + private AbstractManagementActor _logActor; + + @Override + public void setUp() + { + _logActor = new AbstractManagementActor(new NullRootMessageLogger(), AbstractManagementActor.UNKNOWN_PRINCIPAL) + { + @Override + public String getLogMessage() + { + return null; + } + }; + } + + public void testGetPrincipalName() + { + Subject subject = TestPrincipalUtils.createTestSubject("guest"); + + final String principalName = Subject.doAs(subject, + new PrivilegedAction() + { + public String run() + { + return _logActor.getPrincipalName(); + } + }); + + assertEquals("guest", principalName); + } + + public void testGetPrincipalNameUsingSubjectWithoutAuthenticatedPrincipal() + { + Subject subject = new Subject(true, Collections.emptySet(), Collections.emptySet(), Collections.emptySet()); + + final String principalName = Subject.doAs(subject, + new PrivilegedAction() + { + public String run() + { + return _logActor.getPrincipalName(); + } + }); + + assertEquals(AbstractManagementActor.UNKNOWN_PRINCIPAL, principalName); + } + + public void testGetPrincipalWithoutSubject() + { + assertEquals(AbstractManagementActor.UNKNOWN_PRINCIPAL, _logActor.getPrincipalName()); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseActorTestCase.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseActorTestCase.java index ec2cdd5585..30c3a51604 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseActorTestCase.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseActorTestCase.java @@ -20,39 +20,39 @@ */ package org.apache.qpid.server.logging.actors; -import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogMessage; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.logging.UnitTestMessageLogger; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class BaseActorTestCase extends InternalBrokerBaseCase +public class BaseActorTestCase extends QpidTestCase { - protected LogActor _amqpActor; - protected UnitTestMessageLogger _rawLogger; - protected RootMessageLogger _rootLogger; + private boolean _statusUpdatesEnabled = true; + private LogActor _amqpActor; + private UnitTestMessageLogger _rawLogger; + private RootMessageLogger _rootLogger; @Override - public void configure() + public void setUp() throws Exception { - getConfiguration().getConfig().setProperty(ServerConfiguration.STATUS_UPDATES, "on"); - } - - @Override - public void createBroker() throws Exception - { - super.createBroker(); - - _rawLogger = new UnitTestMessageLogger(getConfiguration()); + super.setUp(); + CurrentActor.removeAll(); + CurrentActor.setDefault(null); + _rawLogger = new UnitTestMessageLogger(_statusUpdatesEnabled); _rootLogger = _rawLogger; } + @Override public void tearDown() throws Exception { - _rawLogger.clearLogMessages(); - + if(_rawLogger != null) + { + _rawLogger.clearLogMessages(); + } + CurrentActor.removeAll(); + CurrentActor.setDefault(null); super.tearDown(); } @@ -87,4 +87,34 @@ public class BaseActorTestCase extends InternalBrokerBaseCase }); } + public boolean isStatusUpdatesEnabled() + { + return _statusUpdatesEnabled; + } + + public void setStatusUpdatesEnabled(boolean statusUpdatesEnabled) + { + _statusUpdatesEnabled = statusUpdatesEnabled; + } + + public LogActor getAmqpActor() + { + return _amqpActor; + } + + public void setAmqpActor(LogActor amqpActor) + { + _amqpActor = amqpActor; + } + + public UnitTestMessageLogger getRawLogger() + { + return _rawLogger; + } + + public RootMessageLogger getRootLogger() + { + return _rootLogger; + } + } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java index 956d296dce..09dd48e4d3 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java @@ -20,14 +20,43 @@ */ package org.apache.qpid.server.logging.actors; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.util.BrokerTestHelper; + public class BaseConnectionActorTestCase extends BaseActorTestCase { + private AMQProtocolSession _session; @Override - public void createBroker() throws Exception + public void setUp() throws Exception { - super.createBroker(); + super.setUp(); + BrokerTestHelper.setUp(); + _session = BrokerTestHelper.createSession(); + + setAmqpActor(new AMQPConnectionActor(_session, getRootLogger())); + } - _amqpActor = new AMQPConnectionActor(getSession(), _rootLogger); + @Override + public void tearDown() throws Exception + { + try + { + if (_session != null) + { + _session.getVirtualHost().close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } } + + public AMQProtocolSession getSession() + { + return _session; + } + } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java index f73765f5aa..8ea5510ce6 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java @@ -70,12 +70,7 @@ public class CurrentActorTest extends BaseConnectionActorTestCase */ public void testLIFO() throws AMQException, ConfigurationException { - // This test only needs the local objects created, _session etc. - // So stopping the broker and making them useless will not affect the - // test, but the extra actors the test broker adds will so by stopping - // we remove the session actor and so all is good. - stopBroker(); - + assertTrue("Unexpected actor: " + CurrentActor.get(), CurrentActor.get() instanceof TestLogActor); AMQPConnectionActor connectionActor = new AMQPConnectionActor(getSession(), new NullRootMessageLogger()); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/HttpManagementActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/HttpManagementActorTest.java new file mode 100644 index 0000000000..905de4b639 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/HttpManagementActorTest.java @@ -0,0 +1,94 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.logging.actors; + +import javax.security.auth.Subject; + +import org.apache.qpid.server.security.auth.TestPrincipalUtils; + +import java.security.PrivilegedAction; +import java.util.List; + +public class HttpManagementActorTest extends BaseActorTestCase +{ + private static final String IP = "127.0.0.1"; + private static final int PORT = 1; + private static final String SUFFIX = "(" + IP + ":" + PORT + ")] "; + + @Override + public void setUp() throws Exception + { + super.setUp(); + setAmqpActor(new HttpManagementActor(getRootLogger(), IP, PORT)); + } + + public void testSubjectPrincipalNameAppearance() + { + Subject subject = TestPrincipalUtils.createTestSubject("guest"); + + final String message = Subject.doAs(subject, new PrivilegedAction() + { + public String run() + { + return sendTestLogMessage(getAmqpActor()); + } + }); + + assertNotNull("Test log message is not created!", message); + + List logs = getRawLogger().getLogMessages(); + assertEquals("Message log size not as expected.", 1, logs.size()); + + String logMessage = logs.get(0).toString(); + assertTrue("Message was not found in log message", logMessage.contains(message)); + assertTrue("Message does not contain expected value: " + logMessage, logMessage.contains("[mng:guest" + SUFFIX)); + } + + /** It's necessary to test successive calls because HttpManagementActor caches + * its log message based on principal name */ + public void testGetLogMessageCaching() + { + assertLogMessageWithoutPrincipal(); + assertLogMessageWithPrincipal("my_principal"); + assertLogMessageWithPrincipal("my_principal2"); + assertLogMessageWithoutPrincipal(); + } + + private void assertLogMessageWithoutPrincipal() + { + String message = getAmqpActor().getLogMessage(); + assertEquals("Unexpected log message", "[mng:" + AbstractManagementActor.UNKNOWN_PRINCIPAL + SUFFIX, message); + } + + private void assertLogMessageWithPrincipal(String principalName) + { + Subject subject = TestPrincipalUtils.createTestSubject(principalName); + final String message = Subject.doAs(subject, new PrivilegedAction() + { + public String run() + { + return getAmqpActor().getLogMessage(); + } + }); + + assertEquals("Unexpected log message", "[mng:" + principalName + SUFFIX, message); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java index cb866245f0..a0bfa592db 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/ManagementActorTest.java @@ -20,10 +20,11 @@ */ package org.apache.qpid.server.logging.actors; -import javax.management.remote.JMXPrincipal; import javax.security.auth.Subject; + +import org.apache.qpid.server.security.auth.TestPrincipalUtils; + import java.security.PrivilegedAction; -import java.util.Collections; import java.util.List; public class ManagementActorTest extends BaseActorTestCase @@ -34,10 +35,10 @@ public class ManagementActorTest extends BaseActorTestCase private String _threadName; @Override - public void createBroker() throws Exception + public void setUp() throws Exception { - super.createBroker(); - _amqpActor = new ManagementActor(_rootLogger); + super.setUp(); + setAmqpActor(new ManagementActor(getRootLogger())); // Set the thread name to be the same as a RMI JMX Connection would use _threadName = Thread.currentThread().getName(); @@ -56,14 +57,14 @@ public class ManagementActorTest extends BaseActorTestCase * * The test sends a message then verifies that it entered the logs. * - * The log message should be fully repalaced (no '{n}' values) and should + * The log message should be fully replaced (no '{n}' values) and should * not contain any channel identification. */ public void testConnection() { - final String message = sendTestLogMessage(_amqpActor); + final String message = sendTestLogMessage(getAmqpActor()); - List logs = _rawLogger.getLogMessages(); + List logs = getRawLogger().getLogMessages(); assertEquals("Message log size not as expected.", 1, logs.size()); @@ -94,21 +95,20 @@ public class ManagementActorTest extends BaseActorTestCase */ public void testSubjectPrincipalNameAppearance() { - Subject subject = new Subject(true, Collections.singleton(new JMXPrincipal("guest")), Collections.EMPTY_SET, - Collections.EMPTY_SET); + Subject subject = TestPrincipalUtils.createTestSubject("guest"); final String message = Subject.doAs(subject, new PrivilegedAction() { public String run() { - return sendTestLogMessage(_amqpActor); + return sendTestLogMessage(getAmqpActor()); } }); // Verify that the log message was created assertNotNull("Test log message is not created!", message); - List logs = _rawLogger.getLogMessages(); + List logs = getRawLogger().getLogMessages(); // Verify that at least one log message was added to log assertEquals("Message log size not as expected.", 1, logs.size()); @@ -130,8 +130,8 @@ public class ManagementActorTest extends BaseActorTestCase public void testGetLogMessageWithoutSubjectButWithActorPrincipal() { String principalName = "my_principal"; - _amqpActor = new ManagementActor(_rootLogger, principalName); - String message = _amqpActor.getLogMessage(); + setAmqpActor(new ManagementActor(getRootLogger(), principalName)); + String message = getAmqpActor().getLogMessage(); assertEquals("Unexpected log message", "[mng:" + principalName + "(" + IP + ")] ", message); } @@ -149,7 +149,7 @@ public class ManagementActorTest extends BaseActorTestCase assertLogMessageInRMIThreadWithPrincipal("RMI TCP Connection(1)-" + IP, "my_principal"); Thread.currentThread().setName("RMI TCP Connection(2)-" + IP ); - String message = _amqpActor.getLogMessage(); + String message = getAmqpActor().getLogMessage(); assertEquals("Unexpected log message", "[mng:N/A(" + IP + ")] ", message); assertLogMessageWithoutPrincipal("TEST"); @@ -158,28 +158,26 @@ public class ManagementActorTest extends BaseActorTestCase private void assertLogMessageInRMIThreadWithoutPrincipal(String threadName) { Thread.currentThread().setName(threadName ); - String message = _amqpActor.getLogMessage(); + String message = getAmqpActor().getLogMessage(); assertEquals("Unexpected log message", "[mng:N/A(" + IP + ")] ", message); } private void assertLogMessageWithoutPrincipal(String threadName) { Thread.currentThread().setName(threadName ); - String message = _amqpActor.getLogMessage(); + String message = getAmqpActor().getLogMessage(); assertEquals("Unexpected log message", "[" + threadName +"] ", message); } private void assertLogMessageInRMIThreadWithPrincipal(String threadName, String principalName) { Thread.currentThread().setName(threadName); - Subject subject = new Subject(true, Collections.singleton(new JMXPrincipal(principalName)), Collections.EMPTY_SET, - Collections.EMPTY_SET); - + Subject subject = TestPrincipalUtils.createTestSubject(principalName); final String message = Subject.doAs(subject, new PrivilegedAction() { public String run() { - return _amqpActor.getLogMessage(); + return getAmqpActor().getLogMessage(); } }); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/QueueActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/QueueActorTest.java index 409f7c84b7..2dc44c58ce 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/QueueActorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/QueueActorTest.java @@ -22,14 +22,16 @@ package org.apache.qpid.server.logging.actors; import java.util.List; +import org.apache.qpid.server.util.BrokerTestHelper; + public class QueueActorTest extends BaseConnectionActorTestCase { @Override - public void createBroker() throws Exception + public void setUp() throws Exception { - super.createBroker(); - _amqpActor = new QueueActor(getQueue(), _rootLogger); + super.setUp(); + setAmqpActor(new QueueActor(BrokerTestHelper.createQueue(getName(), getSession().getVirtualHost()), getRootLogger())); } /** @@ -42,9 +44,9 @@ public class QueueActorTest extends BaseConnectionActorTestCase */ public void testQueueActor() { - final String message = sendTestLogMessage(_amqpActor); + final String message = sendTestLogMessage(getAmqpActor()); - List logs = _rawLogger.getLogMessages(); + List logs = getRawLogger().getLogMessages(); assertEquals("Message log size not as expected.", 1, logs.size()); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java index 8eaa165853..58fca488c4 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.logging.actors; import org.apache.qpid.server.subscription.MockSubscription; +import org.apache.qpid.server.util.BrokerTestHelper; import java.util.List; @@ -37,15 +38,15 @@ public class SubscriptionActorTest extends BaseConnectionActorTestCase { @Override - public void createBroker() throws Exception + public void setUp() throws Exception { - super.createBroker(); + super.setUp(); MockSubscription mockSubscription = new MockSubscription(); - mockSubscription.setQueue(getQueue(), false); + mockSubscription.setQueue(BrokerTestHelper.createQueue(getName(), getSession().getVirtualHost()), false); - _amqpActor = new SubscriptionActor(_rootLogger, mockSubscription); + setAmqpActor(new SubscriptionActor(getRootLogger(), mockSubscription)); } /** @@ -58,9 +59,9 @@ public class SubscriptionActorTest extends BaseConnectionActorTestCase */ public void testSubscription() { - final String message = sendTestLogMessage(_amqpActor); + final String message = sendTestLogMessage(getAmqpActor()); - List logs = _rawLogger.getLogMessages(); + List logs = getRawLogger().getLogMessages(); assertEquals("Message log size not as expected.", 1, logs.size()); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java deleted file mode 100644 index f871baffe6..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java +++ /dev/null @@ -1,245 +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.logging.log4j; - -import java.io.File; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Level; -import org.apache.qpid.util.FileUtils; - -import junit.framework.TestCase; - -public class LoggingFacadeTest extends TestCase -{ - private LoggingFacade _loggingFacade; - private String _log4jXmlFile; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - _log4jXmlFile = createTestLog4jXml(); - _loggingFacade = LoggingFacade.configure(_log4jXmlFile); - } - - public void testGetAvailableLoggerLevels() throws Exception - { - List levels = _loggingFacade.getAvailableLoggerLevels(); - assertTrue(levels.contains("ALL")); - assertTrue(levels.contains("TRACE")); - assertTrue(levels.contains("DEBUG")); - assertTrue(levels.contains("INFO")); - assertTrue(levels.contains("WARN")); - assertTrue(levels.contains("ERROR")); - assertTrue(levels.contains("FATAL")); - assertTrue(levels.contains("OFF")); - assertEquals(8, levels.size()); - } - - public void testRetrieveConfigFileRootLoggerLevel() throws Exception - { - String level = _loggingFacade.retrieveConfigFileRootLoggerLevel(); - assertEquals(Level.WARN.toString(), level); - } - - public void testSetConfigFileRootLoggerLevel() throws Exception - { - String oldLevel = _loggingFacade.retrieveConfigFileRootLoggerLevel(); - assertEquals("WARN", oldLevel); - - _loggingFacade.setConfigFileRootLoggerLevel("INFO"); - - String level = _loggingFacade.retrieveConfigFileRootLoggerLevel(); - assertEquals("INFO", level); - } - - public void testRetrieveConfigFileLoggerLevels() throws Exception - { - Map levels = _loggingFacade.retrieveConfigFileLoggersLevels(); - assertEquals(3, levels.size()); - String abcLevel = levels.get("a.b.c"); - String abc1Level = levels.get("a.b.c.1"); - String abc2Level = levels.get("a.b.c.2"); - assertEquals("INFO", abcLevel); - assertEquals("DEBUG", abc1Level); - assertEquals("TRACE", abc2Level); - } - - public void testSetConfigFileLoggerLevels() throws Exception - { - final String loggerName = "a.b.c"; - - assertConfigFileLoggingLevel(loggerName, "INFO"); - - _loggingFacade.setConfigFileLoggerLevel(loggerName, "WARN"); - - Map levels = _loggingFacade.retrieveConfigFileLoggersLevels(); - String abcLevel = levels.get(loggerName); - assertEquals("WARN", abcLevel); - } - - public void testSetConfigFileLoggerLevelsWhereLoggerDoesNotExist() throws Exception - { - try - { - _loggingFacade.setConfigFileLoggerLevel("does.not.exist", "WARN"); - fail("Exception not thrown"); - } - catch (LoggingFacadeException lfe) - { - // PASS - assertEquals("Can't find logger does.not.exist", lfe.getMessage()); - } - } - - public void testRetrieveRuntimeRootLoggerLevel() throws Exception - { - String level = _loggingFacade.retrieveRuntimeRootLoggerLevel(); - assertEquals(Level.WARN.toString(), level); - } - - public void testSetRuntimeRootLoggerLevel() throws Exception - { - String oldLevel = _loggingFacade.retrieveRuntimeRootLoggerLevel(); - assertEquals("WARN", oldLevel); - - _loggingFacade.setRuntimeRootLoggerLevel("INFO"); - - String level = _loggingFacade.retrieveRuntimeRootLoggerLevel(); - assertEquals("INFO", level); - } - - public void testRetrieveRuntimeLoggersLevels() throws Exception - { - Map levels = _loggingFacade.retrieveRuntimeLoggersLevels(); - // Don't assert size as implementation itself uses logging and we'd count its loggers too - String abcLevel = levels.get("a.b.c"); - String abc1Level = levels.get("a.b.c.1"); - String abc2Level = levels.get("a.b.c.2"); - assertEquals("INFO", abcLevel); - assertEquals("DEBUG", abc1Level); - assertEquals("TRACE", abc2Level); - } - - public void testSetRuntimeLoggerLevel() throws Exception - { - final String loggerName = "a.b.c"; - - assertRuntimeLoggingLevel(loggerName, "INFO"); - - _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN"); - - assertRuntimeLoggingLevel(loggerName, "WARN"); - } - - public void testSetRuntimeLoggerToInheritFromParent() throws Exception - { - final String parentLoggerName = "a.b.c"; - final String childLoggerName = "a.b.c.1"; - - assertRuntimeLoggingLevel(parentLoggerName, "INFO"); - assertRuntimeLoggingLevel(childLoggerName, "DEBUG"); - - _loggingFacade.setRuntimeLoggerLevel(childLoggerName, null); - - assertRuntimeLoggingLevel(parentLoggerName, "INFO"); - assertRuntimeLoggingLevel(childLoggerName, "INFO"); - } - - public void testSetRuntimeLoggerLevelsWhereLoggerDoesNotExist() throws Exception - { - final String loggerName = "does.not.exist2"; - - Map oldLevels = _loggingFacade.retrieveRuntimeLoggersLevels(); - assertFalse(oldLevels.containsKey(loggerName)); - - try - { - _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN"); - fail("Exception not thrown"); - } - catch (LoggingFacadeException lfe) - { - // PASS - assertEquals("Can't find logger " + loggerName, lfe.getMessage()); - } - - Map levels = _loggingFacade.retrieveRuntimeLoggersLevels(); - assertFalse(levels.containsKey(loggerName)); - } - - public void testReloadOfChangedLog4JFileUpdatesRuntimeLogLevel() throws Exception - { - final String loggerName = "a.b.c"; - - assertRuntimeLoggingLevel(loggerName, "INFO"); - assertConfigFileLoggingLevel(loggerName, "INFO"); - - _loggingFacade.setConfigFileLoggerLevel(loggerName, "WARN"); - - assertRuntimeLoggingLevel(loggerName, "INFO"); - - _loggingFacade.reload(); - - assertRuntimeLoggingLevel(loggerName, "WARN"); - } - - - public void testReloadOfLog4JFileRevertsRuntimeChanges() throws Exception - { - final String loggerName = "a.b.c"; - - assertRuntimeLoggingLevel(loggerName, "INFO"); - assertConfigFileLoggingLevel(loggerName, "INFO"); - - _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN"); - - assertRuntimeLoggingLevel(loggerName, "WARN"); - - _loggingFacade.reload(); - - assertRuntimeLoggingLevel(loggerName, "INFO"); - } - - private void assertConfigFileLoggingLevel(final String loggerName, String expectedLevel) throws Exception - { - Map levels = _loggingFacade.retrieveConfigFileLoggersLevels(); - String actualLevel = levels.get(loggerName); - assertEquals(expectedLevel, actualLevel); - } - - private void assertRuntimeLoggingLevel(final String loggerName, String expectedLevel) throws Exception - { - Map levels = _loggingFacade.retrieveRuntimeLoggersLevels(); - String actualLevel = levels.get(loggerName); - assertEquals(expectedLevel, actualLevel); - } - - private String createTestLog4jXml() throws Exception - { - File dst = File.createTempFile("log4j." + getName(), "xml"); - File filename = new File(getClass().getResource("LoggingFacadeTest.log4j.xml").toURI()); - FileUtils.copy(filename, dst); - dst.deleteOnExit(); - return dst.getAbsolutePath(); - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingManagementFacadeTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingManagementFacadeTest.java new file mode 100644 index 0000000000..72b34868ba --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingManagementFacadeTest.java @@ -0,0 +1,243 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.logging.log4j; + +import java.io.File; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Level; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.util.FileUtils; + +import junit.framework.TestCase; + +public class LoggingManagementFacadeTest extends TestCase +{ + private LoggingManagementFacade _loggingFacade; + private String _log4jXmlFile; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _log4jXmlFile = createTestLog4jXml(); + _loggingFacade = LoggingManagementFacade.configure(_log4jXmlFile); + } + + public void testGetAvailableLoggerLevels() throws Exception + { + List levels = _loggingFacade.getAvailableLoggerLevels(); + assertTrue(levels.contains("ALL")); + assertTrue(levels.contains("TRACE")); + assertTrue(levels.contains("DEBUG")); + assertTrue(levels.contains("INFO")); + assertTrue(levels.contains("WARN")); + assertTrue(levels.contains("ERROR")); + assertTrue(levels.contains("FATAL")); + assertTrue(levels.contains("OFF")); + assertEquals(8, levels.size()); + } + + public void testRetrieveConfigFileRootLoggerLevel() throws Exception + { + String level = _loggingFacade.retrieveConfigFileRootLoggerLevel(); + assertEquals(Level.WARN.toString(), level); + } + + public void testSetConfigFileRootLoggerLevel() throws Exception + { + String oldLevel = _loggingFacade.retrieveConfigFileRootLoggerLevel(); + assertEquals("WARN", oldLevel); + + _loggingFacade.setConfigFileRootLoggerLevel("INFO"); + + String level = _loggingFacade.retrieveConfigFileRootLoggerLevel(); + assertEquals("INFO", level); + } + + public void testRetrieveConfigFileLoggerLevels() throws Exception + { + Map levels = _loggingFacade.retrieveConfigFileLoggersLevels(); + assertEquals(3, levels.size()); + String abcLevel = levels.get("a.b.c"); + String abc1Level = levels.get("a.b.c.1"); + String abc2Level = levels.get("a.b.c.2"); + assertEquals("INFO", abcLevel); + assertEquals("DEBUG", abc1Level); + assertEquals("TRACE", abc2Level); + } + + public void testSetConfigFileLoggerLevels() throws Exception + { + final String loggerName = "a.b.c"; + + assertConfigFileLoggingLevel(loggerName, "INFO"); + + _loggingFacade.setConfigFileLoggerLevel(loggerName, "WARN"); + + Map levels = _loggingFacade.retrieveConfigFileLoggersLevels(); + String abcLevel = levels.get(loggerName); + assertEquals("WARN", abcLevel); + } + + public void testSetConfigFileLoggerLevelsWhereLoggerDoesNotExist() throws Exception + { + try + { + _loggingFacade.setConfigFileLoggerLevel("does.not.exist", "WARN"); + fail("Exception not thrown"); + } + catch (LoggingFacadeException lfe) + { + // PASS + assertEquals("Can't find logger does.not.exist", lfe.getMessage()); + } + } + + public void testRetrieveRuntimeRootLoggerLevel() throws Exception + { + String level = _loggingFacade.retrieveRuntimeRootLoggerLevel(); + assertEquals(Level.WARN.toString(), level); + } + + public void testSetRuntimeRootLoggerLevel() throws Exception + { + String oldLevel = _loggingFacade.retrieveRuntimeRootLoggerLevel(); + assertEquals("WARN", oldLevel); + + _loggingFacade.setRuntimeRootLoggerLevel("INFO"); + + String level = _loggingFacade.retrieveRuntimeRootLoggerLevel(); + assertEquals("INFO", level); + } + + public void testRetrieveRuntimeLoggersLevels() throws Exception + { + Map levels = _loggingFacade.retrieveRuntimeLoggersLevels(); + // Don't assert size as implementation itself uses logging and we'd count its loggers too + String abcLevel = levels.get("a.b.c"); + String abc1Level = levels.get("a.b.c.1"); + String abc2Level = levels.get("a.b.c.2"); + assertEquals("INFO", abcLevel); + assertEquals("DEBUG", abc1Level); + assertEquals("TRACE", abc2Level); + } + + public void testSetRuntimeLoggerLevel() throws Exception + { + final String loggerName = "a.b.c"; + + assertRuntimeLoggingLevel(loggerName, "INFO"); + + _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN"); + + assertRuntimeLoggingLevel(loggerName, "WARN"); + } + + public void testSetRuntimeLoggerToInheritFromParent() throws Exception + { + final String parentLoggerName = "a.b.c"; + final String childLoggerName = "a.b.c.1"; + + assertRuntimeLoggingLevel(parentLoggerName, "INFO"); + assertRuntimeLoggingLevel(childLoggerName, "DEBUG"); + + _loggingFacade.setRuntimeLoggerLevel(childLoggerName, null); + + assertRuntimeLoggingLevel(parentLoggerName, "INFO"); + assertRuntimeLoggingLevel(childLoggerName, "INFO"); + } + + public void testSetRuntimeLoggerLevelsWhereLoggerDoesNotExist() throws Exception + { + final String loggerName = "does.not.exist2"; + + Map oldLevels = _loggingFacade.retrieveRuntimeLoggersLevels(); + assertFalse(oldLevels.containsKey(loggerName)); + + try + { + _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN"); + fail("Exception not thrown"); + } + catch (LoggingFacadeException lfe) + { + // PASS + assertEquals("Can't find logger " + loggerName, lfe.getMessage()); + } + + Map levels = _loggingFacade.retrieveRuntimeLoggersLevels(); + assertFalse(levels.containsKey(loggerName)); + } + + public void testReloadOfChangedLog4JFileUpdatesRuntimeLogLevel() throws Exception + { + final String loggerName = "a.b.c"; + + assertRuntimeLoggingLevel(loggerName, "INFO"); + assertConfigFileLoggingLevel(loggerName, "INFO"); + + _loggingFacade.setConfigFileLoggerLevel(loggerName, "WARN"); + + assertRuntimeLoggingLevel(loggerName, "INFO"); + + _loggingFacade.reload(); + + assertRuntimeLoggingLevel(loggerName, "WARN"); + } + + + public void testReloadOfLog4JFileRevertsRuntimeChanges() throws Exception + { + final String loggerName = "a.b.c"; + + assertRuntimeLoggingLevel(loggerName, "INFO"); + assertConfigFileLoggingLevel(loggerName, "INFO"); + + _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN"); + + assertRuntimeLoggingLevel(loggerName, "WARN"); + + _loggingFacade.reload(); + + assertRuntimeLoggingLevel(loggerName, "INFO"); + } + + private void assertConfigFileLoggingLevel(final String loggerName, String expectedLevel) throws Exception + { + Map levels = _loggingFacade.retrieveConfigFileLoggersLevels(); + String actualLevel = levels.get(loggerName); + assertEquals(expectedLevel, actualLevel); + } + + private void assertRuntimeLoggingLevel(final String loggerName, String expectedLevel) throws Exception + { + Map levels = _loggingFacade.retrieveRuntimeLoggersLevels(); + String actualLevel = levels.get(loggerName); + assertEquals(expectedLevel, actualLevel); + } + + private String createTestLog4jXml() throws Exception + { + return TestFileUtils.createTempFileFromResource(this, "LoggingFacadeTest.log4j.xml").getAbsolutePath(); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java index 24e7225d82..229d75c69f 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java @@ -29,11 +29,12 @@ import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.UnitTestMessageLogger; import org.apache.qpid.server.logging.actors.TestLogActor; import org.apache.qpid.server.logging.subjects.TestBlankSubject; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; import java.util.List; -public abstract class AbstractTestMessages extends InternalBrokerBaseCase +public abstract class AbstractTestMessages extends QpidTestCase { protected Configuration _config = new PropertiesConfiguration(); protected LogMessage _logMessage = null; @@ -49,6 +50,14 @@ public abstract class AbstractTestMessages extends InternalBrokerBaseCase _logger = new UnitTestMessageLogger(); _actor = new TestLogActor(_logger); + BrokerTestHelper.setUp(); + } + + @Override + public void tearDown() throws Exception + { + BrokerTestHelper.tearDown(); + super.tearDown(); } protected List performLog() diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java index 4364376000..1cb4da55c3 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java @@ -21,7 +21,7 @@ package org.apache.qpid.server.logging.messages; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.util.BrokerTestHelper; import java.util.List; @@ -30,12 +30,9 @@ import java.util.List; */ public class ExchangeMessagesTest extends AbstractTestMessages { - public void testExchangeCreated_Transient() + public void testExchangeCreated_Transient() throws Exception { - // Get the Default Exchange on the Test Vhost for testing - Exchange exchange = ApplicationRegistry.getInstance(). - getVirtualHostRegistry().getVirtualHost("test"). - getExchangeRegistry().getDefaultExchange(); + Exchange exchange = BrokerTestHelper.createExchange("test"); String type = exchange.getTypeShortString().toString(); String name = exchange.getNameShortString().toString(); @@ -48,12 +45,9 @@ public class ExchangeMessagesTest extends AbstractTestMessages validateLogMessage(log, "EXH-1001", expected); } - public void testExchangeCreated_Persistent() + public void testExchangeCreated_Persistent() throws Exception { - // Get the Default Exchange on the Test Vhost for testing - Exchange exchange = ApplicationRegistry.getInstance(). - getVirtualHostRegistry().getVirtualHost("test"). - getExchangeRegistry().getDefaultExchange(); + Exchange exchange = BrokerTestHelper.createExchange("test"); String type = exchange.getTypeShortString().toString(); String name = exchange.getNameShortString().toString(); @@ -76,12 +70,9 @@ public class ExchangeMessagesTest extends AbstractTestMessages validateLogMessage(log, "EXH-1002", expected); } - public void testExchangeDiscardedMessage() + public void testExchangeDiscardedMessage() throws Exception { - // Get the Default Exchange on the Test Vhost for testing - final Exchange exchange = ApplicationRegistry.getInstance(). - getVirtualHostRegistry().getVirtualHost("test"). - getExchangeRegistry().getDefaultExchange(); + Exchange exchange = BrokerTestHelper.createExchange("test"); final String name = exchange.getNameShortString().toString(); final String routingKey = "routingKey"; diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ManagementConsoleMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ManagementConsoleMessagesTest.java index 4bfbae44ac..dfc9357402 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ManagementConsoleMessagesTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ManagementConsoleMessagesTest.java @@ -29,10 +29,10 @@ public class ManagementConsoleMessagesTest extends AbstractTestMessages { public void testManagementStartup() { - _logMessage = ManagementConsoleMessages.STARTUP(); + _logMessage = ManagementConsoleMessages.STARTUP("My"); List log = performLog(); - String[] expected = {"Startup"}; + String[] expected = {"My Management Startup"}; validateLogMessage(log, "MNG-1001", expected); } @@ -65,29 +65,20 @@ public class ManagementConsoleMessagesTest extends AbstractTestMessages public void testManagementReady() { - _logMessage = ManagementConsoleMessages.READY(false); + _logMessage = ManagementConsoleMessages.READY("My"); List log = performLog(); - String[] expected = {"Ready"}; - - validateLogMessage(log, "MNG-1004", expected); - - _logger.clearLogMessages(); - - _logMessage = ManagementConsoleMessages.READY(true); - log = performLog(); - - expected = new String[]{"Ready : Using the platform JMX Agent"}; + String[] expected = {"My Management Ready"}; validateLogMessage(log, "MNG-1004", expected); } public void testManagementStopped() { - _logMessage = ManagementConsoleMessages.STOPPED(); + _logMessage = ManagementConsoleMessages.STOPPED("My"); List log = performLog(); - String[] expected = {"Stopped"}; + String[] expected = {"My Management Stopped"}; validateLogMessage(log, "MNG-1005", expected); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/AbstractTestLogSubject.java b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/AbstractTestLogSubject.java index c2558d2d1b..193e8a490d 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/AbstractTestLogSubject.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/AbstractTestLogSubject.java @@ -20,21 +20,19 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogMessage; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.UnitTestMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.TestLogActor; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; import java.util.List; @@ -49,29 +47,39 @@ import java.util.List; * The resulting log file is then validated. * */ -public abstract class AbstractTestLogSubject extends InternalBrokerBaseCase +public abstract class AbstractTestLogSubject extends QpidTestCase { - protected Configuration _config = new PropertiesConfiguration(); protected LogSubject _subject = null; @Override public void setUp() throws Exception { super.setUp(); - - _config.setProperty(ServerConfiguration.STATUS_UPDATES, "ON"); + BrokerTestHelper.setUp(); } + @Override + public void tearDown() throws Exception + { + BrokerTestHelper.tearDown(); + try + { + CurrentActor.removeAll(); + } + finally + { + super.tearDown(); + } + } - protected List performLog() throws ConfigurationException + protected List performLog(boolean statusUpdatesEnabled) { if (_subject == null) { throw new NullPointerException("LogSubject has not been set"); } - ServerConfiguration serverConfig = new ServerConfiguration(_config); - UnitTestMessageLogger logger = new UnitTestMessageLogger(serverConfig); + UnitTestMessageLogger logger = new UnitTestMessageLogger(statusUpdatesEnabled); LogActor actor = new TestLogActor(logger); @@ -247,11 +255,10 @@ public abstract class AbstractTestLogSubject extends InternalBrokerBaseCase /** * Test that when Logging occurs a single log statement is provided * - * @throws ConfigurationException */ - public void testEnabled() throws ConfigurationException + public void testEnabled() { - List logs = performLog(); + List logs = performLog(true); assertEquals("Log has incorrect message count", 1, logs.size()); @@ -267,15 +274,11 @@ public abstract class AbstractTestLogSubject extends InternalBrokerBaseCase protected abstract void validateLogStatement(String message); /** - * Ensure that when status-updates are off this does not perform logging - * - * @throws ConfigurationException + * Ensure that when status updates are off this does not perform logging */ - public void testDisabled() throws ConfigurationException + public void testDisabled() { - _config.setProperty(ServerConfiguration.STATUS_UPDATES, "OFF"); - - List logs = performLog(); + List logs = performLog(false); assertEquals("Log has incorrect message count", 0, logs.size()); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java index e80c4c4679..dd8d28e836 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java @@ -24,7 +24,7 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; /** @@ -38,13 +38,12 @@ public class BindingLogSubjectTest extends AbstractTestLogSubject private Exchange _exchange; private VirtualHost _testVhost; + @Override public void setUp() throws Exception { super.setUp(); - _testVhost = ApplicationRegistry.getInstance().getVirtualHostRegistry(). - getVirtualHost("test"); - // Configure items for subjectCreation + _testVhost = BrokerTestHelper.createVirtualHost("test"); _routingKey = new AMQShortString("RoutingKey"); _exchange = _testVhost.getExchangeRegistry().getDefaultExchange(); _queue = new MockAMQQueue("BindingLogSubjectTest"); @@ -53,6 +52,16 @@ public class BindingLogSubjectTest extends AbstractTestLogSubject _subject = new BindingLogSubject(String.valueOf(_routingKey), _exchange, _queue); } + @Override + public void tearDown() throws Exception + { + if (_testVhost != null) + { + _testVhost.close(); + } + super.tearDown(); + } + /** * Validate that the logged Subject message is as expected: * MESSAGE [Blank][vh(/test)/ex(direct/<>)/qu(BindingLogSubjectTest)/rk(RoutingKey)] diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java index 6bc5effa05..d75e033739 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java @@ -34,6 +34,7 @@ public class ChannelLogSubjectTest extends ConnectionLogSubjectTest { super.setUp(); + AMQChannel channel = new AMQChannel(getSession(), _channelID, getSession().getVirtualHost().getMessageStore()); _subject = new ChannelLogSubject(channel); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java index c246fff2a8..7dc4c443ba 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java @@ -20,17 +20,34 @@ */ package org.apache.qpid.server.logging.subjects; +import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.util.BrokerTestHelper; + /** * Validate ConnectionLogSubjects are logged as expected */ public class ConnectionLogSubjectTest extends AbstractTestLogSubject { + private InternalTestProtocolSession _session; + + @Override public void setUp() throws Exception { super.setUp(); - _subject = new ConnectionLogSubject(getSession()); + _session = BrokerTestHelper.createSession("test"); + _subject = new ConnectionLogSubject(_session); + } + + @Override + public void tearDown() throws Exception + { + if (_session != null) + { + _session.getVirtualHost().close(); + } + super.tearDown(); } /** @@ -40,7 +57,12 @@ public class ConnectionLogSubjectTest extends AbstractTestLogSubject */ protected void validateLogStatement(String message) { - verifyConnection(getSession().getSessionID(), "InternalTestProtocolSession", "127.0.0.1:1", "test", message); + verifyConnection(_session.getSessionID(), "InternalTestProtocolSession", "127.0.0.1:1", "test", message); + } + + public InternalTestProtocolSession getSession() + { + return _session; } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubjectTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubjectTest.java index cc06b05bf6..8d1b89bf3c 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubjectTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubjectTest.java @@ -21,7 +21,7 @@ package org.apache.qpid.server.logging.subjects; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -33,17 +33,27 @@ public class ExchangeLogSubjectTest extends AbstractTestLogSubject private Exchange _exchange; private VirtualHost _testVhost; + @Override public void setUp() throws Exception { super.setUp(); - _testVhost = ApplicationRegistry.getInstance().getVirtualHostRegistry(). - getVirtualHost("test"); + _testVhost = BrokerTestHelper.createVirtualHost("test"); _exchange = _testVhost.getExchangeRegistry().getDefaultExchange(); _subject = new ExchangeLogSubject(_exchange,_testVhost); } + @Override + public void tearDown() throws Exception + { + if (_testVhost != null) + { + _testVhost.close(); + } + super.tearDown(); + } + /** * Validate that the logged Subject message is as expected: * MESSAGE [Blank][vh(/test)/ex(direct/<>)] diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java index c62b24c3b9..65fd249d03 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; /** @@ -30,16 +30,26 @@ public class MessageStoreLogSubjectTest extends AbstractTestLogSubject { private VirtualHost _testVhost; + @Override public void setUp() throws Exception { super.setUp(); - _testVhost = ApplicationRegistry.getInstance().getVirtualHostRegistry(). - getVirtualHost("test"); + _testVhost = BrokerTestHelper.createVirtualHost("test"); _subject = new MessageStoreLogSubject(_testVhost, _testVhost.getMessageStore().getClass().getSimpleName()); } + @Override + public void tearDown() throws Exception + { + if (_testVhost != null) + { + _testVhost.close(); + } + super.tearDown(); + } + /** * Validate that the logged Subject message is as expected: * MESSAGE [Blank][vh(/test)/ms(MemoryMessageStore)] diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/QueueLogSubjectTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/QueueLogSubjectTest.java index 1f432be57a..e2765f338b 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/QueueLogSubjectTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/QueueLogSubjectTest.java @@ -22,7 +22,7 @@ package org.apache.qpid.server.logging.subjects; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; /** @@ -39,8 +39,7 @@ public class QueueLogSubjectTest extends AbstractTestLogSubject { super.setUp(); - _testVhost = ApplicationRegistry.getInstance().getVirtualHostRegistry(). - getVirtualHost("test"); + _testVhost = BrokerTestHelper.createVirtualHost("test"); _queue = new MockAMQQueue("QueueLogSubjectTest"); ((MockAMQQueue) _queue).setVirtualHost(_testVhost); @@ -48,6 +47,16 @@ public class QueueLogSubjectTest extends AbstractTestLogSubject _subject = new QueueLogSubject(_queue); } + @Override + public void tearDown() throws Exception + { + if (_testVhost != null) + { + _testVhost.close(); + } + super.tearDown(); + } + /** * Validate that the logged Subject message is as expected: * MESSAGE [Blank][vh(/test)/qu(QueueLogSubjectTest)] diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java index 0c356e1838..153d01f355 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java @@ -23,12 +23,13 @@ package org.apache.qpid.server.logging.subjects; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.flow.LimitlessCreditManager; +import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionFactory; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; /** @@ -42,23 +43,24 @@ public class SubscriptionLogSubjectTest extends AbstractTestLogSubject private int _channelID = 1; private Subscription _subscription; + @Override public void setUp() throws Exception { super.setUp(); - _testVhost = ApplicationRegistry.getInstance().getVirtualHostRegistry(). - getVirtualHost("test"); + InternalTestProtocolSession session = BrokerTestHelper.createSession(); + _testVhost = session.getVirtualHost(); _queue = new MockAMQQueue("SubscriptionLogSubjectTest"); ((MockAMQQueue) _queue).setVirtualHost(_testVhost); - AMQChannel channel = new AMQChannel(getSession(), _channelID, getSession().getVirtualHost().getMessageStore()); + AMQChannel channel = new AMQChannel(session, _channelID, _testVhost.getMessageStore()); - getSession().addChannel(channel); + session.addChannel(channel); SubscriptionFactory factory = new SubscriptionFactoryImpl(); - _subscription = factory.createSubscription(_channelID, getSession(), new AMQShortString("cTag"), + _subscription = factory.createSubscription(_channelID, session, new AMQShortString("cTag"), false, null, false, new LimitlessCreditManager()); @@ -67,6 +69,16 @@ public class SubscriptionLogSubjectTest extends AbstractTestLogSubject _subject = new SubscriptionLogSubject(_subscription); } + @Override + public void tearDown() throws Exception + { + if (_testVhost != null) + { + _testVhost.close(); + } + super.tearDown(); + } + /** * Validate that the logged Subject message is as expected: * MESSAGE [Blank][sub:0(vh(/test)/qu(SubscriptionLogSubjectTest))] diff --git a/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java b/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java new file mode 100644 index 0000000000..7c1db6348b --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/model/BrokerShutdownTest.java @@ -0,0 +1,189 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.configuration.startup.DefaultRecovererProvider; +import org.apache.qpid.server.logging.LogRecorder; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory; +import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; + +import java.io.File; +import java.security.Provider; +import java.security.Security; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * QPID-1390 : Test to validate that the AuthenticationManger can successfully unregister any new SASL providers when + * the broker is stopped. + */ +public class BrokerShutdownTest extends QpidTestCase +{ + private Provider[] _defaultProviders; + private Broker _broker; + private TaskExecutor _taskExecutor; + + @Override + public void setUp() throws Exception + { + // Get default providers + _defaultProviders = Security.getProviders(); + + super.setUp(); + + _taskExecutor = new TaskExecutor(); + _taskExecutor.start(); + + // Startup the new broker and register the new providers + _broker = startBroker(); + } + + @Override + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + if (_taskExecutor != null) + { + _taskExecutor.stopImmediately(); + } + } + + } + + private Broker startBroker() throws Exception + { + ConfigurationEntryStore store = mock(ConfigurationEntryStore.class); + UUID brokerId = UUID.randomUUID(); + UUID authenticationProviderId = UUID.randomUUID(); + + ConfigurationEntry root = new ConfigurationEntry(brokerId, Broker.class.getSimpleName(), Collections. emptyMap(), + Collections.singleton(authenticationProviderId), store); + + File file = TestFileUtils.createTempFile(BrokerShutdownTest.this, ".db.users"); + Map attributes = new HashMap(); + attributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + attributes.put(PlainPasswordFileAuthenticationManagerFactory.ATTRIBUTE_PATH, file.getAbsolutePath()); + ConfigurationEntry authenticationProviderEntry = new ConfigurationEntry(authenticationProviderId, AuthenticationProvider.class.getSimpleName(), attributes, + Collections. emptySet(), store); + + when(store.getRootEntry()).thenReturn(root); + when(store.getEntry(brokerId)).thenReturn(root); + when(store.getEntry(authenticationProviderId)).thenReturn(authenticationProviderEntry); + + // mocking the required object + StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class); + VirtualHostRegistry virtualHostRegistry = mock(VirtualHostRegistry.class); + LogRecorder logRecorder = mock(LogRecorder.class); + RootMessageLogger rootMessageLogger = mock(RootMessageLogger.class); + + // recover the broker from the store + RecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, _taskExecutor); + ConfiguredObjectRecoverer brokerRecoverer = provider.getRecoverer(Broker.class.getSimpleName()); + + Broker broker = (Broker) brokerRecoverer.create(provider, store.getRootEntry()); + + // start broker + broker.setDesiredState(State.INITIALISING, State.ACTIVE); + return broker; + } + + private void stopBroker() + { + _broker.setDesiredState(State.ACTIVE, State.STOPPED); + } + + /** + * QPID-1399 : Ensure that the Authentication manager unregisters any SASL providers created during + * broker start-up. + * + */ + public void testAuthenticationMangerCleansUp() throws Exception + { + + // Get the providers after initialisation + Provider[] providersAfterInitialisation = Security.getProviders(); + + // Find the additions + List additions = new LinkedList(); + for (Provider afterInit : providersAfterInitialisation) + { + boolean found = false; + for (Provider defaultProvider : _defaultProviders) + { + if (defaultProvider == afterInit) + { + found = true; + break; + } + } + + // Record added registies + if (!found) + { + additions.add(afterInit); + } + } + + assertFalse("No new SASL mechanisms added by initialisation.", additions.isEmpty()); + + // Close the registry which will perform the close the + // AuthenticationManager + stopBroker(); + + // Validate that the SASL plugins have been removed. + Provider[] providersAfterClose = Security.getProviders(); + + assertTrue("No providers unregistered", providersAfterInitialisation.length > providersAfterClose.length); + + // Ensure that the additions are not still present after close(). + for (Provider afterClose : providersAfterClose) + { + assertFalse("Added provider not unregistered", additions.contains(afterClose)); + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java b/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java index 643132d371..c686a24e99 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java @@ -70,8 +70,12 @@ public class UUIDGeneratorTest extends QpidTestCase idSet.add(id6); UUID id7 = UUIDGenerator.generateVhostAliasUUID(value, value); idSet.add(id7); + UUID id8 = UUIDGenerator.generateGroupUUID(value, value); + idSet.add(id8); + UUID id9 = UUIDGenerator.generateGroupMemberUUID(value, value, value); + idSet.add(id9); - assertEquals("The produced UUIDs were not all unique", 7, idSet.size()); + assertEquals("The produced UUIDs were not all unique", 9, idSet.size()); } public void testQueueIdGeneration() throws Exception diff --git a/java/broker/src/test/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactoryTest.java new file mode 100644 index 0000000000..585fecae83 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactoryTest.java @@ -0,0 +1,85 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import junit.framework.TestCase; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; + +public class AuthenticationProviderFactoryTest extends TestCase +{ + + public void testCreatePasswordCredentialManagingAuthenticationProvider() + { + AuthenticationProvider provider = testForFactory(mock(PrincipalDatabaseAuthenticationManager.class)); + assertTrue("The created provider should match the factory's AuthenticationManager type", + provider instanceof PasswordCredentialManagingAuthenticationProvider); + } + + public void testCreateNonPasswordCredentialManagingAuthenticationProvider() + { + AuthenticationProvider provider = testForFactory(mock(AuthenticationManager.class)); + assertFalse("The created provider should match the factory's AuthenticationManager type", + provider instanceof PasswordCredentialManagingAuthenticationProvider); + } + + @SuppressWarnings("unchecked") + private AuthenticationProvider testForFactory(AuthenticationManager authenticationManager) + { + UUID id = UUID.randomUUID(); + Map attributes = new HashMap(); + + QpidServiceLoader authManagerFactoryServiceLoader = mock(QpidServiceLoader.class); + AuthenticationManagerFactory authenticationManagerFactory = mock(AuthenticationManagerFactory.class); + ConfigurationEntry configurationEntry = mock(ConfigurationEntry.class); + + when(configurationEntry.getId()).thenReturn(id); + Broker broker = mock(Broker.class); + + when(authManagerFactoryServiceLoader.atLeastOneInstanceOf(AuthenticationManagerFactory.class)).thenReturn( + Collections.singleton(authenticationManagerFactory)); + when(authenticationManagerFactory.createInstance(attributes)).thenReturn(authenticationManager); + + AuthenticationProviderFactory providerFactory = new AuthenticationProviderFactory(authManagerFactoryServiceLoader); + AuthenticationProvider provider = providerFactory.create(id, broker, attributes, null); + + assertNotNull("Provider is not created", provider); + assertEquals("Unexpected ID", id, provider.getId()); + + return provider; + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java new file mode 100644 index 0000000000..14c5c265c9 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java @@ -0,0 +1,212 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import static org.mockito.Mockito.mock; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.test.utils.QpidTestCase; + +public class PortFactoryTest extends QpidTestCase +{ + private UUID _portId = UUID.randomUUID(); + private int _portNumber = 123; + private Set _tcpStringSet = Collections.singleton(Transport.SSL.name()); + private Set _tcpTransportSet = Collections.singleton(Transport.SSL); + + private Map _attributes = new HashMap(); + + private Broker _broker = mock(Broker.class); + private PortFactory _portFactory; + + @Override + protected void setUp() throws Exception + { + setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, null); + setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES, null); + _portFactory = new PortFactory(); + + _attributes.put(Port.PORT, _portNumber); + _attributes.put(Port.TRANSPORTS, _tcpStringSet); + + _attributes.put(Port.TCP_NO_DELAY, "true"); + _attributes.put(Port.RECEIVE_BUFFER_SIZE, "1"); + _attributes.put(Port.SEND_BUFFER_SIZE, "2"); + _attributes.put(Port.NEED_CLIENT_AUTH, "true"); + _attributes.put(Port.WANT_CLIENT_AUTH, "true"); + _attributes.put(Port.BINDING_ADDRESS, "127.0.0.1"); + } + + public void testDefaultProtocols() + { + Collection protocols = _portFactory.getDefaultProtocols(); + EnumSet expected = EnumSet.of(Protocol.AMQP_0_8, Protocol.AMQP_0_9, Protocol.AMQP_0_9_1, Protocol.AMQP_0_10, + Protocol.AMQP_1_0); + assertEquals("Unexpected protocols", new HashSet(expected), new HashSet(protocols)); + } + + public void testDefaultProtocolsWhenProtocolExcludeSystemPropertyIsSet() + { + setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, Protocol.AMQP_1_0.name() + "," + + Protocol.AMQP_0_10.name()); + _portFactory = new PortFactory(); + Collection protocols = _portFactory.getDefaultProtocols(); + EnumSet expected = EnumSet.of(Protocol.AMQP_0_8, Protocol.AMQP_0_9, Protocol.AMQP_0_9_1); + assertEquals("Unexpected protocols", new HashSet(expected), new HashSet(protocols)); + } + + public void testDefaultProtocolsWhenProtocolIncludeSystemPropertyIsSet() + { + setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, Protocol.AMQP_1_0.name() + "," + + Protocol.AMQP_0_10.name() + "," + Protocol.AMQP_0_9_1.name()); + setTestSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES, Protocol.AMQP_0_10.name() + "," + + Protocol.AMQP_0_9_1.name()); + _portFactory = new PortFactory(); + Collection protocols = _portFactory.getDefaultProtocols(); + EnumSet expected = EnumSet.of(Protocol.AMQP_0_8, Protocol.AMQP_0_9, Protocol.AMQP_0_9_1, Protocol.AMQP_0_10); + assertEquals("Unexpected protocols", new HashSet(expected), new HashSet(protocols)); + } + + public void testCreatePortWithMinimumAttributes() + { + Map attributes = new HashMap(); + attributes.put(Port.PORT, 1); + Port port = _portFactory.createPort(_portId, _broker, attributes); + + assertNotNull(port); + assertTrue(port instanceof AmqpPortAdapter); + assertEquals("Unexpected port", 1, port.getPort()); + assertEquals("Unexpected transports", Collections.singleton(PortFactory.DEFAULT_TRANSPORT), port.getTransports()); + assertEquals("Unexpected protocols", _portFactory.getDefaultProtocols(), port.getProtocols()); + assertEquals("Unexpected send buffer size", PortFactory.DEFAULT_AMQP_SEND_BUFFER_SIZE, + port.getAttribute(Port.SEND_BUFFER_SIZE)); + assertEquals("Unexpected receive buffer size", PortFactory.DEFAULT_AMQP_RECEIVE_BUFFER_SIZE, + port.getAttribute(Port.RECEIVE_BUFFER_SIZE)); + assertEquals("Unexpected need client auth", PortFactory.DEFAULT_AMQP_NEED_CLIENT_AUTH, + port.getAttribute(Port.NEED_CLIENT_AUTH)); + assertEquals("Unexpected want client auth", PortFactory.DEFAULT_AMQP_WANT_CLIENT_AUTH, + port.getAttribute(Port.WANT_CLIENT_AUTH)); + assertEquals("Unexpected tcp no delay", PortFactory.DEFAULT_AMQP_TCP_NO_DELAY, port.getAttribute(Port.TCP_NO_DELAY)); + assertEquals("Unexpected binding", PortFactory.DEFAULT_AMQP_BINDING, port.getAttribute(Port.BINDING_ADDRESS)); + } + + public void testCreateAmqpPort() + { + Set amqp010ProtocolSet = Collections.singleton(Protocol.AMQP_0_10); + Set amqp010StringSet = Collections.singleton(Protocol.AMQP_0_10.name()); + _attributes.put(Port.PROTOCOLS, amqp010StringSet); + + Port port = _portFactory.createPort(_portId, _broker, _attributes); + + assertNotNull(port); + assertTrue(port instanceof AmqpPortAdapter); + assertEquals(_portId, port.getId()); + assertEquals(_portNumber, port.getPort()); + assertEquals(_tcpTransportSet, port.getTransports()); + assertEquals(amqp010ProtocolSet, port.getProtocols()); + assertEquals("Unexpected send buffer size", 2, port.getAttribute(Port.SEND_BUFFER_SIZE)); + assertEquals("Unexpected receive buffer size", 1, port.getAttribute(Port.RECEIVE_BUFFER_SIZE)); + assertEquals("Unexpected need client auth", true, port.getAttribute(Port.NEED_CLIENT_AUTH)); + assertEquals("Unexpected want client auth", true, port.getAttribute(Port.WANT_CLIENT_AUTH)); + assertEquals("Unexpected tcp no delay", true, port.getAttribute(Port.TCP_NO_DELAY)); + assertEquals("Unexpected binding", "127.0.0.1", port.getAttribute(Port.BINDING_ADDRESS)); + } + + public void testCreateNonAmqpPort() + { + Set nonAmqpProtocolSet = Collections.singleton(Protocol.JMX_RMI); + Set nonAmqpStringSet = Collections.singleton(Protocol.JMX_RMI.name()); + _attributes = new HashMap(); + _attributes.put(Port.PROTOCOLS, nonAmqpStringSet); + _attributes.put(Port.PORT, _portNumber); + _attributes.put(Port.TRANSPORTS, _tcpStringSet); + + Port port = _portFactory.createPort(_portId, _broker, _attributes); + + assertNotNull(port); + assertFalse("Port should be a PortAdapter, not its AMQP-specific subclass", port instanceof AmqpPortAdapter); + assertEquals(_portId, port.getId()); + assertEquals(_portNumber, port.getPort()); + assertEquals(_tcpTransportSet, port.getTransports()); + assertEquals(nonAmqpProtocolSet, port.getProtocols()); + assertNull("Unexpected send buffer size", port.getAttribute(Port.SEND_BUFFER_SIZE)); + assertNull("Unexpected receive buffer size", port.getAttribute(Port.RECEIVE_BUFFER_SIZE)); + assertNull("Unexpected need client auth", port.getAttribute(Port.NEED_CLIENT_AUTH)); + assertNull("Unexpected want client auth", port.getAttribute(Port.WANT_CLIENT_AUTH)); + assertNull("Unexpected tcp no delay", port.getAttribute(Port.TCP_NO_DELAY)); + assertNull("Unexpected binding", port.getAttribute(Port.BINDING_ADDRESS)); + } + + public void testCreateNonAmqpPortWithPartiallySetAttributes() + { + Set nonAmqpProtocolSet = Collections.singleton(Protocol.JMX_RMI); + Set nonAmqpStringSet = Collections.singleton(Protocol.JMX_RMI.name()); + _attributes = new HashMap(); + _attributes.put(Port.PROTOCOLS, nonAmqpStringSet); + _attributes.put(Port.PORT, _portNumber); + + Port port = _portFactory.createPort(_portId, _broker, _attributes); + + assertNotNull(port); + assertFalse("Port should be a PortAdapter, not its AMQP-specific subclass", port instanceof AmqpPortAdapter); + assertEquals(_portId, port.getId()); + assertEquals(_portNumber, port.getPort()); + assertEquals(Collections.singleton(PortFactory.DEFAULT_TRANSPORT), port.getTransports()); + assertEquals(nonAmqpProtocolSet, port.getProtocols()); + assertNull("Unexpected send buffer size", port.getAttribute(Port.SEND_BUFFER_SIZE)); + assertNull("Unexpected receive buffer size", port.getAttribute(Port.RECEIVE_BUFFER_SIZE)); + assertNull("Unexpected need client auth", port.getAttribute(Port.NEED_CLIENT_AUTH)); + assertNull("Unexpected want client auth", port.getAttribute(Port.WANT_CLIENT_AUTH)); + assertNull("Unexpected tcp no delay", port.getAttribute(Port.TCP_NO_DELAY)); + assertNull("Unexpected binding", port.getAttribute(Port.BINDING_ADDRESS)); + } + + public void testCreateMixedAmqpAndNonAmqpThrowsException() + { + Set mixedProtocolSet = new HashSet(Arrays.asList(Protocol.AMQP_0_10.name(), Protocol.JMX_RMI.name())); + _attributes.put(Port.PROTOCOLS, mixedProtocolSet); + + try + { + _portFactory.createPort(_portId, _broker, _attributes); + fail("Exception not thrown"); + } + catch (IllegalConfigurationException e) + { + // pass + } + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/model/configuration/ConfigurationEntryTest.java b/java/broker/src/test/java/org/apache/qpid/server/model/configuration/ConfigurationEntryTest.java new file mode 100644 index 0000000000..dd48d7b56d --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/model/configuration/ConfigurationEntryTest.java @@ -0,0 +1,129 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.configuration; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import junit.framework.TestCase; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHost; + +public class ConfigurationEntryTest extends TestCase +{ + public void testGetChildren() + { + ConfigurationEntryStore store = mock(ConfigurationEntryStore.class); + + ConfigurationEntry virtualHostEntry1 = new ConfigurationEntry(UUID.randomUUID(), VirtualHost.class.getSimpleName(), + Collections. emptyMap(), Collections. emptySet(), store); + ConfigurationEntry virtualHostEntry2 = new ConfigurationEntry(UUID.randomUUID(), VirtualHost.class.getSimpleName(), + Collections. emptyMap(), Collections. emptySet(), store); + ConfigurationEntry portEntry = new ConfigurationEntry(UUID.randomUUID(), Port.class.getSimpleName(), + Collections. emptyMap(), Collections. emptySet(), store); + + when(store.getEntry(virtualHostEntry1.getId())).thenReturn(virtualHostEntry1); + when(store.getEntry(virtualHostEntry2.getId())).thenReturn(virtualHostEntry2); + when(store.getEntry(portEntry.getId())).thenReturn(portEntry); + + Set childrenIds = new HashSet(); + childrenIds.add(virtualHostEntry1.getId()); + childrenIds.add(virtualHostEntry2.getId()); + childrenIds.add(portEntry.getId()); + ConfigurationEntry parentEntry = new ConfigurationEntry(UUID.randomUUID(), Broker.class.getSimpleName(), + Collections. emptyMap(), childrenIds, store); + + Map> children = parentEntry.getChildren(); + assertNotNull("Null is returned for children", children); + assertEquals("Unexpected size", 2, children.size()); + Collection virtualHosts = children.get(VirtualHost.class.getSimpleName()); + Collection ports = children.get(Port.class.getSimpleName()); + assertEquals("Unexpected virtual hosts", + new HashSet(Arrays.asList(virtualHostEntry1, virtualHostEntry2)), + new HashSet(virtualHosts)); + assertEquals("Unexpected ports", new HashSet(Arrays.asList(portEntry)), + new HashSet(ports)); + } + + public void testHashCode() + { + ConfigurationEntryStore store = mock(ConfigurationEntryStore.class); + + UUID id = UUID.randomUUID(); + ConfigurationEntry entry1 = new ConfigurationEntry(id, VirtualHost.class.getSimpleName(), + Collections. emptyMap(), Collections.singleton(UUID.randomUUID()), store); + ConfigurationEntry entry2 = new ConfigurationEntry(id, VirtualHost.class.getSimpleName(), + Collections. emptyMap(), Collections.singleton(UUID.randomUUID()), store); + ConfigurationEntry entryWithDifferentId = new ConfigurationEntry(UUID.randomUUID(), + VirtualHost.class.getSimpleName(), Collections. emptyMap(), Collections.singleton(UUID.randomUUID()), store); + + assertTrue(entry1.hashCode() == entry2.hashCode()); + assertFalse(entry1.hashCode() == entryWithDifferentId.hashCode()); + } + + public void testEqualsObject() + { + ConfigurationEntryStore store = mock(ConfigurationEntryStore.class); + + UUID id = UUID.randomUUID(); + Map attributes1 = new HashMap(); + attributes1.put(VirtualHost.NAME, "name1"); + Set childrenIds = Collections.singleton(UUID.randomUUID()); + ConfigurationEntry entry1 = new ConfigurationEntry(id, VirtualHost.class.getSimpleName(), attributes1, + childrenIds, store); + + Map attributes2 = new HashMap(); + attributes2.put(VirtualHost.NAME, "name2"); + + ConfigurationEntry entry2 = new ConfigurationEntry(id, VirtualHost.class.getSimpleName(), attributes1, + childrenIds, store); + ConfigurationEntry entryWithDifferentId = new ConfigurationEntry(UUID.randomUUID(), + VirtualHost.class.getSimpleName(), attributes1, childrenIds, store); + + assertTrue(entry1.equals(entry2)); + assertFalse("Entries should be diferrent because of diferrent IDs", entry1.equals(entryWithDifferentId)); + + ConfigurationEntry entryWithDifferentChildId = new ConfigurationEntry(id, + VirtualHost.class.getSimpleName(), attributes1, Collections.singleton(UUID.randomUUID()), store); + assertFalse("Entries should be diferrent because of diferrent children", entry1.equals(entryWithDifferentChildId)); + + ConfigurationEntry entryWithDifferentName = new ConfigurationEntry(id, + VirtualHost.class.getSimpleName(), attributes2, childrenIds, store); + assertFalse("Entries should be diferrent because of diferrent attributes", entry1.equals(entryWithDifferentName)); + + ConfigurationEntry entryWithDifferentType = new ConfigurationEntry(id, + Broker.class.getSimpleName(), attributes1, childrenIds, store); + assertFalse("Entries should be diferrent because of diferrent types", entry1.equals(entryWithDifferentType)); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java b/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java deleted file mode 100644 index 20abdd48cd..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.plugins; - -import org.osgi.framework.Version; - -import org.apache.qpid.test.utils.QpidTestCase; - -import java.util.Map; -import java.util.TreeMap; - -/** - * - */ -public class OsgiSystemPackageUtilTest extends QpidTestCase -{ - private OsgiSystemPackageUtil _util = null; // Object under test - - private Map _map = new TreeMap(); // Use a TreeMap for unit test in order for determinstic results. - - public void testWithOnePackage() throws Exception - { - _map.put("org.xyz", "1.0.0"); - - _util = new OsgiSystemPackageUtil(null, _map); - - final String systemPackageString = _util.getFormattedSystemPackageString(); - - assertEquals("org.xyz; version=1.0.0", systemPackageString); - } - - public void testWithTwoPackages() throws Exception - { - _map.put("org.xyz", "1.0.0"); - _map.put("org.abc", "1.2.3"); - - _util = new OsgiSystemPackageUtil(null, _map); - - final String systemPackageString = _util.getFormattedSystemPackageString(); - - assertEquals("org.abc; version=1.2.3, org.xyz; version=1.0.0", systemPackageString); - } - - public void testWithNoPackages() throws Exception - { - _util = new OsgiSystemPackageUtil(null, _map); - - final String systemPackageString = _util.getFormattedSystemPackageString(); - - assertNull(systemPackageString); - } - - public void testWithQpidPackageWithQpidReleaseNumberSet() throws Exception - { - _map.put("org.apache.qpid.xyz", "1.0.0"); - _map.put("org.abc", "1.2.3"); - - _util = new OsgiSystemPackageUtil(new Version("0.19"), _map); - - final String systemPackageString = _util.getFormattedSystemPackageString(); - - assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=0.19.0", systemPackageString); - } - - public void testWithQpidPackageWithoutQpidReleaseNumberSet() throws Exception - { - _map.put("org.apache.qpid.xyz", "1.0.0"); - _map.put("org.abc", "1.2.3"); - - _util = new OsgiSystemPackageUtil(null, _map); - - final String systemPackageString = _util.getFormattedSystemPackageString(); - - assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=1.0.0", systemPackageString); - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/plugins/PluginTest.java b/java/broker/src/test/java/org/apache/qpid/server/plugins/PluginTest.java deleted file mode 100644 index b4bda9a032..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/plugins/PluginTest.java +++ /dev/null @@ -1,55 +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.plugins; - -import org.apache.qpid.server.exchange.ExchangeType; -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -import java.util.Map; - -public class PluginTest extends InternalBrokerBaseCase -{ - private static final String TEST_EXCHANGE_CLASS = "org.apache.qpid.extras.exchanges.example.TestExchangeType"; - - private static final String PLUGIN_DIRECTORY = System.getProperty("example.plugin.target"); - private static final String CACHE_DIRECTORY = System.getProperty("example.cache.target"); - - @Override - public void configure() - { - getConfiguration().getConfig().addProperty("plugin-directory", PLUGIN_DIRECTORY); - getConfiguration().getConfig().addProperty("cache-directory", CACHE_DIRECTORY); - } - - public void disabled_testLoadExchanges() throws Exception - { - PluginManager manager = getRegistry().getPluginManager(); - Map> exchanges = manager.getExchanges(); - assertNotNull("No exchanges found in " + PLUGIN_DIRECTORY, exchanges); - assertEquals("Wrong number of exchanges found in " + PLUGIN_DIRECTORY, 2, exchanges.size()); - assertNotNull("Wrong exchange found in " + PLUGIN_DIRECTORY, exchanges.get(TEST_EXCHANGE_CLASS)); - } - - public void testNoExchanges() throws Exception - { - PluginManager manager = new PluginManager("/path/to/nowhere", "/tmp", null); - Map> exchanges = manager.getExchanges(); - assertTrue("Exchanges found", exchanges.isEmpty()); - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java index 96c67941f9..3216f8886a 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java +++ b/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java @@ -28,10 +28,11 @@ import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.MessageContentSource; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionImpl; @@ -39,6 +40,8 @@ import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.TestNetworkConnection; import javax.security.auth.Subject; + +import java.security.Principal; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -55,19 +58,28 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr private AtomicInteger _deliveryCount = new AtomicInteger(0); private static final AtomicLong ID_GENERATOR = new AtomicLong(0); - public InternalTestProtocolSession(VirtualHost virtualHost) throws AMQException + public InternalTestProtocolSession(VirtualHost virtualHost, Broker broker) throws AMQException { - super(ApplicationRegistry.getInstance().getVirtualHostRegistry(), new TestNetworkConnection(), ID_GENERATOR.getAndIncrement()); + super(broker, new TestNetworkConnection(), ID_GENERATOR.getAndIncrement()); _channelDelivers = new HashMap>>(); - // Need to authenticate session for it to be representative testing. - setAuthorizedSubject(new Subject(true, Collections.singleton(new UsernamePrincipal("InternalTestProtocolSession")), - Collections.EMPTY_SET, Collections.EMPTY_SET)); - + setTestAuthorizedSubject(); setVirtualHost(virtualHost); } + private void setTestAuthorizedSubject() + { + Principal principal = new AuthenticatedPrincipal(new UsernamePrincipal("InternalTestProtocolSession")); + Subject authorizedSubject = new Subject( + true, + Collections.singleton(principal), + Collections.emptySet(), + Collections.emptySet()); + + setAuthorizedSubject(authorizedSubject); + } + public ProtocolOutputConverter getProtocolOutputConverter() { return this; diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java index e8ee2c4d0b..99dd42e179 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java @@ -23,20 +23,24 @@ package org.apache.qpid.server.protocol; import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; -import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; /** Test class to test MBean operations for AMQMinaProtocolSession. */ -public class MaxChannelsTest extends InternalBrokerBaseCase +public class MaxChannelsTest extends QpidTestCase { - private AMQProtocolEngine _session; + private AMQProtocolEngine _session; - public void testChannels() throws Exception + @Override + public void setUp() throws Exception { - VirtualHost vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"); - _session = new InternalTestProtocolSession(vhost); + super.setUp(); + BrokerTestHelper.setUp(); + _session = BrokerTestHelper.createSession(); + } + public void testChannels() throws Exception + { // check the channel count is correct int channelCount = _session.getChannels().size(); assertEquals("Initial channel count wrong", 0, channelCount); @@ -45,13 +49,15 @@ public class MaxChannelsTest extends InternalBrokerBaseCase _session.setMaximumNumberOfChannels(maxChannels); assertEquals("Number of channels not correctly set.", new Long(maxChannels), _session.getMaximumNumberOfChannels()); + for (long currentChannel = 0L; currentChannel < maxChannels; currentChannel++) + { + _session.addChannel(new AMQChannel(_session, (int) currentChannel, null)); + } try { - for (long currentChannel = 0L; currentChannel < maxChannels; currentChannel++) - { - _session.addChannel(new AMQChannel(_session, (int) currentChannel, null)); - } + _session.addChannel(new AMQChannel(_session, (int) maxChannels, null)); + fail("Cannot create more channels then maximum"); } catch (AMQException e) { @@ -63,14 +69,14 @@ public class MaxChannelsTest extends InternalBrokerBaseCase @Override public void tearDown() throws Exception { - try { - _session.closeSession(); - } catch (AMQException e) { - // Yikes - fail(e.getMessage()); - } + try + { + _session.getVirtualHost().close(); + _session.closeSession(); + } finally { + BrokerTestHelper.tearDown(); super.tearDown(); } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java index 6081be8efd..02b8c74feb 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java @@ -20,36 +20,52 @@ */ package org.apache.qpid.server.protocol; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.TestApplicationRegistry; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.transport.TestNetworkConnection; +import static org.mockito.Mockito.when; import java.nio.ByteBuffer; import java.util.EnumSet; import java.util.Set; +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.transport.TestNetworkConnection; + public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase { + private VirtualHost _virtualHost; + private Broker _broker; + @Override protected void setUp() throws Exception { super.setUp(); + BrokerTestHelper.setUp(); + _broker = BrokerTestHelper.createBrokerMock(); + VirtualHostRegistry virtualHostRegistry = _broker.getVirtualHostRegistry(); + when(_broker.getAttribute(Broker.DEFAULT_VIRTUAL_HOST)).thenReturn("default"); - //the factory needs a registry instance - ApplicationRegistry.initialise(new TestApplicationRegistry(new ServerConfiguration(new XMLConfiguration()))); + // AMQP 1-0 connection needs default vhost to be present + _virtualHost = BrokerTestHelper.createVirtualHost("default", virtualHostRegistry); } - protected void tearDown() + @Override + protected void tearDown() throws Exception { - //the factory opens a registry instance - ApplicationRegistry.remove(); + try + { + _virtualHost.close(); + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } } - + private static final byte[] AMQP_0_8_HEADER = new byte[] { (byte) 'A', (byte) 'M', @@ -108,6 +124,7 @@ public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase (byte) 0 }; + private byte[] getAmqpHeader(final AmqpProtocolVersion version) { switch(version) @@ -137,7 +154,7 @@ public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase Set versions = EnumSet.allOf(AmqpProtocolVersion.class); MultiVersionProtocolEngineFactory factory = - new MultiVersionProtocolEngineFactory(versions, null); + new MultiVersionProtocolEngineFactory(_broker, versions, null); //create a dummy to retrieve the 'current' ID number long previousId = factory.newProtocolEngine().getConnectionId(); @@ -160,6 +177,7 @@ public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase assertEquals("ID was not as expected following receipt of the AMQP version header", expectedID, engine.getConnectionId()); previousId = expectedID; + engine.closed(); } } @@ -174,7 +192,7 @@ public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase try { - new MultiVersionProtocolEngineFactory(versions, AmqpProtocolVersion.v0_9); + new MultiVersionProtocolEngineFactory(_broker, versions, AmqpProtocolVersion.v0_9); fail("should not have been allowed to create the factory"); } catch(IllegalArgumentException iae) diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java index c3d58f3bdc..81ad57c040 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java @@ -36,8 +36,9 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest @Override public void setUp() throws Exception { - _arguments = new FieldTable(); - _arguments.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), 3); + FieldTable arguments = new FieldTable(); + arguments.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), 3); + setArguments(arguments); super.setUp(); } @@ -45,25 +46,26 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest { // Enqueue messages in order - _queue.enqueue(createMessage(1L, (byte) 10)); - _queue.enqueue(createMessage(2L, (byte) 4)); - _queue.enqueue(createMessage(3L, (byte) 0)); + SimpleAMQQueue queue = getQueue(); + queue.enqueue(createMessage(1L, (byte) 10)); + queue.enqueue(createMessage(2L, (byte) 4)); + queue.enqueue(createMessage(3L, (byte) 0)); // Enqueue messages in reverse order - _queue.enqueue(createMessage(4L, (byte) 0)); - _queue.enqueue(createMessage(5L, (byte) 4)); - _queue.enqueue(createMessage(6L, (byte) 10)); + queue.enqueue(createMessage(4L, (byte) 0)); + queue.enqueue(createMessage(5L, (byte) 4)); + queue.enqueue(createMessage(6L, (byte) 10)); // Enqueue messages out of order - _queue.enqueue(createMessage(7L, (byte) 4)); - _queue.enqueue(createMessage(8L, (byte) 10)); - _queue.enqueue(createMessage(9L, (byte) 0)); + queue.enqueue(createMessage(7L, (byte) 4)); + queue.enqueue(createMessage(8L, (byte) 10)); + queue.enqueue(createMessage(9L, (byte) 0)); // Register subscriber - _queue.registerSubscription(_subscription, false); + queue.registerSubscription(getSubscription(), false); Thread.sleep(150); - ArrayList msgs = _subscription.getMessages(); + ArrayList msgs = getSubscription().getMessages(); try { assertEquals(1L, msgs.get(0).getMessage().getMessageNumber()); diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java index 186be4dff7..0f82345271 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java @@ -20,23 +20,23 @@ */ package org.apache.qpid.server.queue; +import static org.mockito.Mockito.when; + import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.DefaultExchangeFactory; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.logging.SystemOutMessageLogger; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.TestLogActor; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.util.TestApplicationRegistry; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; @@ -50,19 +50,19 @@ public class AMQQueueFactoryTest extends QpidTestCase { super.setUp(); - CurrentActor.set(new TestLogActor(new SystemOutMessageLogger())); - + BrokerTestHelper.setUp(); XMLConfiguration configXml = new XMLConfiguration(); - configXml.addProperty("virtualhosts.virtualhost(-1).name", getName()); - configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName()); + configXml.addProperty("store.class", TestableMemoryMessageStore.class.getName()); - ServerConfiguration configuration = new ServerConfiguration(configXml); - ApplicationRegistry registry = new TestApplicationRegistry(configuration); - ApplicationRegistry.initialise(registry); - registry.getVirtualHostRegistry().setDefaultVirtualHostName(getName()); + Broker broker = BrokerTestHelper.createBrokerMock(); + if (getName().equals("testDeadLetterQueueDoesNotInheritDLQorMDCSettings")) + { + when(broker.getAttribute(Broker.MAXIMUM_DELIVERY_ATTEMPTS)).thenReturn(5); + when(broker.getAttribute(Broker.DEAD_LETTER_QUEUE_ENABLED)).thenReturn(true); + } - _virtualHost = registry.getVirtualHostRegistry().getVirtualHost(getName()); + _virtualHost = BrokerTestHelper.createVirtualHost(new VirtualHostConfiguration(getName(), configXml, broker)); _queueRegistry = _virtualHost.getQueueRegistry(); @@ -73,11 +73,12 @@ public class AMQQueueFactoryTest extends QpidTestCase { try { - super.tearDown(); + _virtualHost.close(); } finally { - ApplicationRegistry.remove(); + BrokerTestHelper.tearDown(); + super.tearDown(); } } @@ -172,11 +173,8 @@ public class AMQQueueFactoryTest extends QpidTestCase * are not applied to the DLQ itself. * @throws AMQException */ - public void testDeadLetterQueueDoesNotInheritDLQorMDCSettings() throws AMQException + public void testDeadLetterQueueDoesNotInheritDLQorMDCSettings() throws Exception { - ApplicationRegistry.getInstance().getConfiguration().getConfig().addProperty("deadLetterQueues","true"); - ApplicationRegistry.getInstance().getConfiguration().getConfig().addProperty("maximumDeliveryCount","5"); - String queueName = "testDeadLetterQueueEnabled"; AMQShortString dlExchangeName = new AMQShortString(queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); @@ -336,11 +334,8 @@ public class AMQQueueFactoryTest extends QpidTestCase try { // change DLQ name to make its length bigger than exchange name - ApplicationRegistry.getInstance().getConfiguration().getConfig() - .addProperty("deadLetterExchangeSuffix", "_DLE"); - ApplicationRegistry.getInstance().getConfiguration().getConfig() - .addProperty("deadLetterQueueSuffix", "_DLQUEUE"); - + setTestSystemProperty(BrokerProperties.PROPERTY_DEAD_LETTER_EXCHANGE_SUFFIX, "_DLE"); + setTestSystemProperty(BrokerProperties.PROPERTY_DEAD_LETTER_QUEUE_SUFFIX, "_DLQUEUE"); FieldTable fieldTable = new FieldTable(); fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", @@ -353,13 +348,6 @@ public class AMQQueueFactoryTest extends QpidTestCase assertTrue("Unexpected exception message!", e.getMessage().contains("DLQ queue name") && e.getMessage().contains("length exceeds limit of 255")); } - finally - { - ApplicationRegistry.getInstance().getConfiguration().getConfig() - .addProperty("deadLetterExchangeSuffix", DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); - ApplicationRegistry.getInstance().getConfiguration().getConfig() - .addProperty("deadLetterQueueSuffix", AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); - } } /** @@ -372,11 +360,8 @@ public class AMQQueueFactoryTest extends QpidTestCase try { // change DLQ name to make its length bigger than exchange name - ApplicationRegistry.getInstance().getConfiguration().getConfig() - .addProperty("deadLetterExchangeSuffix", "_DLEXCHANGE"); - ApplicationRegistry.getInstance().getConfiguration().getConfig() - .addProperty("deadLetterQueueSuffix", "_DLQ"); - + setTestSystemProperty(BrokerProperties.PROPERTY_DEAD_LETTER_EXCHANGE_SUFFIX, "_DLEXCHANGE"); + setTestSystemProperty(BrokerProperties.PROPERTY_DEAD_LETTER_QUEUE_SUFFIX, "_DLQ"); FieldTable fieldTable = new FieldTable(); fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", @@ -389,13 +374,6 @@ public class AMQQueueFactoryTest extends QpidTestCase assertTrue("Unexpected exception message!", e.getMessage().contains("DL exchange name") && e.getMessage().contains("length exceeds limit of 255")); } - finally - { - ApplicationRegistry.getInstance().getConfiguration().getConfig() - .addProperty("deadLetterExchangeSuffix", DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); - ApplicationRegistry.getInstance().getConfiguration().getConfig() - .addProperty("deadLetterQueueSuffix", AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); - } } private String generateStringWithLength(char ch, int length) diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java index 190d5c777b..cbbf183232 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java @@ -32,18 +32,16 @@ import org.apache.qpid.server.flow.LimitlessCreditManager; import org.apache.qpid.server.flow.Pre0_10CreditManager; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; import java.util.ArrayList; import java.util.Set; @@ -51,7 +49,7 @@ import java.util.Set; /** * Tests that acknowledgements are handled correctly. */ -public class AckTest extends InternalBrokerBaseCase +public class AckTest extends QpidTestCase { private Subscription _subscription; @@ -70,15 +68,19 @@ public class AckTest extends InternalBrokerBaseCase public void setUp() throws Exception { super.setUp(); - _virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"); - _messageStore = new TestableMemoryMessageStore(); - _protocolSession = new InternalTestProtocolSession(_virtualHost); - _channel = new AMQChannel(_protocolSession,5, _messageStore /*dont need exchange registry*/); - - _protocolSession.addChannel(_channel); + BrokerTestHelper.setUp(); + _channel = BrokerTestHelper.createChannel(5); + _protocolSession = _channel.getProtocolSession(); + _virtualHost = _protocolSession.getVirtualHost(); + _queue = BrokerTestHelper.createQueue(getTestName(), _virtualHost); + _messageStore = (TestableMemoryMessageStore)_virtualHost.getMessageStore(); + } - _queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "myQ", false, "guest", true, false, - _virtualHost, null); + @Override + protected void tearDown() throws Exception + { + BrokerTestHelper.tearDown(); + super.tearDown(); } private void publishMessages(int count) throws AMQException diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java new file mode 100644 index 0000000000..2f160678ba --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java @@ -0,0 +1,97 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.queue; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.test.utils.QpidTestCase; + +public class InboundMessageAdapterTest extends QpidTestCase +{ + private ServerMessage _mockMessage; + private QueueEntry _mockQueueEntry; + private InboundMessageAdapter _inboundMessageAdapter; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _mockMessage = mock(ServerMessage.class); + _mockQueueEntry = mock(QueueEntry.class); + when(_mockQueueEntry.getMessage()).thenReturn(_mockMessage); + + _inboundMessageAdapter = new InboundMessageAdapter(_mockQueueEntry); + } + + public void testGetRoutingKey() throws Exception + { + String routingKey = getTestName(); + when(_mockMessage.getRoutingKey()).thenReturn(routingKey); + + assertEquals("Unexpected value for routing key", routingKey, _inboundMessageAdapter.getRoutingKey()); + } + + public void testGetRoutingKeyShortString() throws Exception + { + String routingKey = getTestName(); + when(_mockMessage.getRoutingKey()).thenReturn(routingKey); + + AMQShortString routingKeyShortString = AMQShortString.valueOf(routingKey); + assertEquals("Unexpected value for routing key short string", routingKeyShortString, _inboundMessageAdapter.getRoutingKeyShortString()); + } + + public void testGetMessageHeader() throws Exception + { + AMQMessageHeader mockMessageHeader = mock(AMQMessageHeader.class); + when(_mockQueueEntry.getMessageHeader()).thenReturn(mockMessageHeader); + + assertSame("unexpected message header", mockMessageHeader, _inboundMessageAdapter.getMessageHeader()); + } + + public void testIsRedelivered() throws Exception + { + when(_mockQueueEntry.isRedelivered()).thenReturn(true); + assertTrue("unexpected isRedelivered value", _inboundMessageAdapter.isRedelivered()); + + when(_mockQueueEntry.isRedelivered()).thenReturn(false); + assertFalse("unexpected isRedelivered value", _inboundMessageAdapter.isRedelivered()); + } + + public void testIsPersistent() throws Exception + { + when(_mockQueueEntry.isPersistent()).thenReturn(true); + assertTrue("unexpected isPersistent value", _inboundMessageAdapter.isPersistent()); + + when(_mockQueueEntry.isPersistent()).thenReturn(false); + assertFalse("unexpected isPersistent value", _inboundMessageAdapter.isPersistent()); + } + + public void testGetSize() throws Exception + { + long size = 32526215; + when(_mockQueueEntry.getSize()).thenReturn(size); + assertEquals("unexpected getSize value", size, _inboundMessageAdapter.getSize()); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java index bcb8d54636..358246330a 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java @@ -23,10 +23,8 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.QueueConfigType; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.QueueConfiguration; +import org.apache.qpid.server.configuration.plugins.AbstractConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.message.ServerMessage; @@ -106,11 +104,6 @@ public class MockAMQQueue implements AMQQueue return 0; } - public ConfigStore getConfigStore() - { - return getVirtualHost().getConfigStore(); - } - public long getMessageDequeueCount() { return 0; @@ -186,22 +179,6 @@ public class MockAMQQueue implements AMQQueue return null; } - @Override - public UUID getQMFId() - { - return null; - } - - public QueueConfigType getConfigType() - { - return null; - } - - public ConfiguredObject getParent() - { - return null; - } - public boolean isDurable() { return false; @@ -532,16 +509,11 @@ public class MockAMQQueue implements AMQQueue } - public void configure(ConfigurationPlugin config) + public void configure(QueueConfiguration config) { } - public ConfigurationPlugin getConfiguration() - { - return null; - } - public AuthorizationHolder getAuthorizationHolder() { return _authorizationHolder; diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java index 2cd423d4c9..ece42f7de3 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java @@ -28,8 +28,6 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Matchers.contains; import static org.mockito.Matchers.eq; -import org.apache.commons.configuration.PropertiesConfiguration; - import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; @@ -39,7 +37,6 @@ import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.DirectExchange; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.MessageMetaData; @@ -47,16 +44,15 @@ import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.BaseQueue.PostEnqueueAction; import org.apache.qpid.server.queue.SimpleAMQQueue.QueueEntryFilter; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.subscription.MockSubscription; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostImpl; +import org.apache.qpid.test.utils.QpidTestCase; import java.util.ArrayList; import java.util.Collections; @@ -64,17 +60,17 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -public class SimpleAMQQueueTest extends InternalBrokerBaseCase +public class SimpleAMQQueueTest extends QpidTestCase { - protected SimpleAMQQueue _queue; - protected VirtualHost _virtualHost; - protected AMQShortString _qname = new AMQShortString("qname"); - protected AMQShortString _owner = new AMQShortString("owner"); - protected AMQShortString _routingKey = new AMQShortString("routing key"); - protected DirectExchange _exchange; - protected MockSubscription _subscription = new MockSubscription(); - protected FieldTable _arguments = null; + private SimpleAMQQueue _queue; + private VirtualHost _virtualHost; + private AMQShortString _qname = new AMQShortString("qname"); + private AMQShortString _owner = new AMQShortString("owner"); + private AMQShortString _routingKey = new AMQShortString("routing key"); + private DirectExchange _exchange; + private MockSubscription _subscription = new MockSubscription(); + private FieldTable _arguments = null; private MessagePublishInfo info = new MessagePublishInfo() { @@ -108,25 +104,29 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase public void setUp() throws Exception { super.setUp(); - //Create Application Registry for test - ApplicationRegistry applicationRegistry = (ApplicationRegistry)ApplicationRegistry.getInstance(); + BrokerTestHelper.setUp(); - PropertiesConfiguration env = new PropertiesConfiguration(); - final VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration(getClass().getName(), env); - vhostConfig.setMessageStoreClass(TestableMemoryMessageStore.class.getName()); - _virtualHost = new VirtualHostImpl(ApplicationRegistry.getInstance(), vhostConfig); - applicationRegistry.getVirtualHostRegistry().registerVirtualHost(_virtualHost); + _virtualHost = BrokerTestHelper.createVirtualHost(getClass().getName()); - _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), _qname.asString(), false, _owner.asString(), false, false, _virtualHost, FieldTable.convertToMap(_arguments)); + _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), _qname.asString(), false, _owner.asString(), + false, false, _virtualHost, FieldTable.convertToMap(_arguments)); - _exchange = (DirectExchange)_virtualHost.getExchangeRegistry().getExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME); + _exchange = (DirectExchange) _virtualHost.getExchangeRegistry().getExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME); } @Override public void tearDown() throws Exception { - _queue.stop(); - super.tearDown(); + try + { + _queue.stop(); + _virtualHost.close(); + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } } public void testCreateQueue() throws AMQException @@ -659,7 +659,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase public void onRollback() { } - }, 0L); + }); // Check that it is enqueued AMQQueue data = store.getMessages().get(1L); @@ -1269,6 +1269,26 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase } } + public SimpleAMQQueue getQueue() + { + return _queue; + } + + public MockSubscription getSubscription() + { + return _subscription; + } + + public FieldTable getArguments() + { + return _arguments; + } + + public void setArguments(FieldTable arguments) + { + _arguments = arguments; + } + public class TestMessage extends AMQMessage { private final long _tag; diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java index 6b82cd361a..4abb7233dc 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java @@ -20,20 +20,33 @@ */ package org.apache.qpid.server.queue; -import org.apache.qpid.AMQException; import org.apache.qpid.pool.ReferenceCountingExecutorService; import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; -public class SimpleAMQQueueThreadPoolTest extends InternalBrokerBaseCase +public class SimpleAMQQueueThreadPoolTest extends QpidTestCase { - public void test() throws AMQException + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + } + + @Override + public void tearDown() throws Exception + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + + public void test() throws Exception { int initialCount = ReferenceCountingExecutorService.getInstance().getReferenceCount(); - VirtualHost test = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"); + VirtualHost test = BrokerTestHelper.createVirtualHost("test"); try { @@ -50,7 +63,7 @@ public class SimpleAMQQueueThreadPoolTest extends InternalBrokerBaseCase } finally { - ApplicationRegistry.remove(); + test.close(); } } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java b/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java deleted file mode 100644 index 9af950d385..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.registry; - -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -import java.security.Provider; -import java.security.Security; -import java.util.LinkedList; -import java.util.List; - -/** - * QPID-1390 : Test to validate that the AuthenticationManger can successfully unregister any new SASL providers when - * The ApplicationRegistry is closed. - * - * This should be expanded as QPID-1399 is implemented. - */ -public class ApplicationRegistryShutdownTest extends InternalBrokerBaseCase -{ - - private Provider[] _defaultProviders; - @Override - public void setUp() throws Exception - { - // Get default providers - _defaultProviders = Security.getProviders(); - - //Startup the new broker and register the new providers - super.setUp(); - } - - - /** - * QPID-1399 : Ensure that the Authentication manager unregisters any SASL providers created during - * ApplicationRegistry initialisation. - * - */ - public void testAuthenticationMangerCleansUp() throws Exception - { - - // Get the providers after initialisation - Provider[] providersAfterInitialisation = Security.getProviders(); - - // Find the additions - List additions = new LinkedList(); - for (Provider afterInit : providersAfterInitialisation) - { - boolean found = false; - for (Provider defaultProvider : _defaultProviders) - { - if (defaultProvider == afterInit) - { - found=true; - break; - } - } - - // Record added registies - if (!found) - { - additions.add(afterInit); - } - } - - assertFalse("No new SASL mechanisms added by initialisation.", additions.isEmpty()); - - //Close the registry which will perform the close the AuthenticationManager - stopBroker(); - - //Validate that the SASL plugFins have been removed. - Provider[] providersAfterClose = Security.getProviders(); - - assertTrue("No providers unregistered", providersAfterInitialisation.length > providersAfterClose.length); - - //Ensure that the additions are not still present after close(). - for (Provider afterClose : providersAfterClose) - { - assertFalse("Added provider not unregistered", additions.contains(afterClose)); - } - } - - - - - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java new file mode 100644 index 0000000000..b1bc9bea68 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/SubjectCreatorTest.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.security.Principal; +import java.util.Arrays; +import java.util.HashSet; + +import javax.security.auth.Subject; +import javax.security.sasl.SaslServer; + +import junit.framework.TestCase; + +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.group.GroupPrincipalAccessor; + +public class SubjectCreatorTest extends TestCase +{ + private static final String USERNAME = "username"; + private static final String PASSWORD = "password"; + + private AuthenticationManager _authenticationManager = mock(AuthenticationManager.class); + private GroupPrincipalAccessor _groupPrincipalAccessor = mock(GroupPrincipalAccessor.class); + private SubjectCreator _subjectCreator = new SubjectCreator(_authenticationManager, _groupPrincipalAccessor); + + private Principal _userPrincipal = mock(Principal.class); + private Principal _group1 = mock(Principal.class); + private Principal _group2 = mock(Principal.class); + + private AuthenticationResult _authenticationResult; + private SaslServer _testSaslServer = mock(SaslServer.class); + private byte[] _saslResponseBytes = PASSWORD.getBytes(); + + @Override + public void setUp() + { + _authenticationResult = new AuthenticationResult(_userPrincipal); + when(_authenticationManager.authenticate(USERNAME, PASSWORD)).thenReturn(_authenticationResult); + + when(_groupPrincipalAccessor.getGroupPrincipals(USERNAME)) + .thenReturn(new HashSet(Arrays.asList(_group1, _group2))); + } + + public void testAuthenticateUsernameAndPasswordReturnsSubjectWithUserAndGroupPrincipals() + { + final SubjectAuthenticationResult actualResult = _subjectCreator.authenticate(USERNAME, PASSWORD); + + assertEquals(AuthenticationStatus.SUCCESS, actualResult.getStatus()); + + final Subject actualSubject = actualResult.getSubject(); + + assertEquals("Should contain one user principal and two groups ", 3, actualSubject.getPrincipals().size()); + + assertTrue(actualSubject.getPrincipals().contains(new AuthenticatedPrincipal(_userPrincipal))); + assertTrue(actualSubject.getPrincipals().contains(_group1)); + assertTrue(actualSubject.getPrincipals().contains(_group2)); + + assertTrue(actualSubject.isReadOnly()); + } + + public void testSaslAuthenticationSuccessReturnsSubjectWithUserAndGroupPrincipals() throws Exception + { + when(_authenticationManager.authenticate(_testSaslServer, _saslResponseBytes)).thenReturn(_authenticationResult); + when(_testSaslServer.isComplete()).thenReturn(true); + when(_testSaslServer.getAuthorizationID()).thenReturn(USERNAME); + + SubjectAuthenticationResult result = _subjectCreator.authenticate(_testSaslServer, _saslResponseBytes); + + final Subject actualSubject = result.getSubject(); + assertEquals("Should contain one user principal and two groups ", 3, actualSubject.getPrincipals().size()); + + assertTrue(actualSubject.getPrincipals().contains(new AuthenticatedPrincipal(_userPrincipal))); + assertTrue(actualSubject.getPrincipals().contains(_group1)); + assertTrue(actualSubject.getPrincipals().contains(_group2)); + + assertTrue(actualSubject.isReadOnly()); + } + + public void testAuthenticateUnsuccessfulWithUsernameReturnsNullSubjectAndCorrectStatus() + { + testUnsuccessfulAuthentication(AuthenticationResult.AuthenticationStatus.CONTINUE); + testUnsuccessfulAuthentication(AuthenticationResult.AuthenticationStatus.ERROR); + } + + private void testUnsuccessfulAuthentication(AuthenticationStatus expectedStatus) + { + AuthenticationResult failedAuthenticationResult = new AuthenticationResult(expectedStatus); + + when(_authenticationManager.authenticate(USERNAME, PASSWORD)).thenReturn(failedAuthenticationResult); + + SubjectAuthenticationResult subjectAuthenticationResult = _subjectCreator.authenticate(USERNAME, PASSWORD); + + assertSame(expectedStatus, subjectAuthenticationResult.getStatus()); + assertNull(subjectAuthenticationResult.getSubject()); + } + + public void testAuthenticateUnsuccessfulWithSaslServerReturnsNullSubjectAndCorrectStatus() + { + testUnsuccessfulAuthenticationWithSaslServer(AuthenticationResult.AuthenticationStatus.CONTINUE); + testUnsuccessfulAuthenticationWithSaslServer(AuthenticationResult.AuthenticationStatus.ERROR); + } + + private void testUnsuccessfulAuthenticationWithSaslServer(AuthenticationStatus expectedStatus) + { + AuthenticationResult failedAuthenticationResult = new AuthenticationResult(expectedStatus); + + when(_authenticationManager.authenticate(_testSaslServer, _saslResponseBytes)).thenReturn(failedAuthenticationResult); + when(_testSaslServer.isComplete()).thenReturn(false); + + SubjectAuthenticationResult subjectAuthenticationResult = _subjectCreator.authenticate(_testSaslServer, _saslResponseBytes); + + assertSame(expectedStatus, subjectAuthenticationResult.getStatus()); + assertNull(subjectAuthenticationResult.getSubject()); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipalTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipalTest.java new file mode 100644 index 0000000000..cd5791952f --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipalTest.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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; + +import java.security.Principal; + +import javax.security.auth.Subject; + +import org.apache.qpid.server.security.auth.UsernamePrincipal; + +import junit.framework.TestCase; + +public class AuthenticatedPrincipalTest extends TestCase +{ + + private AuthenticatedPrincipal _authenticatedPrincipal = new AuthenticatedPrincipal(new UsernamePrincipal("name")); + + public void testGetAuthenticatedPrincipalFromSubject() + { + final Subject subject = createSubjectContainingAuthenticatedPrincipal(); + final AuthenticatedPrincipal actual = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); + assertSame(_authenticatedPrincipal, actual); + } + + public void testAuthenticatedPrincipalNotInSubject() + { + try + { + AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(new Subject()); + fail("Exception not thrown"); + } + catch (IllegalArgumentException iae) + { + // PASS + } + } + + public void testGetOptionalAuthenticatedPrincipalFromSubject() + { + final Subject subject = createSubjectContainingAuthenticatedPrincipal(); + final AuthenticatedPrincipal actual = AuthenticatedPrincipal.getOptionalAuthenticatedPrincipalFromSubject(subject); + assertSame(_authenticatedPrincipal, actual); + } + + public void testGetOptionalAuthenticatedPrincipalFromSubjectReturnsNullIfMissing() + { + Subject subjectWithNoPrincipals = new Subject(); + assertNull(AuthenticatedPrincipal.getOptionalAuthenticatedPrincipalFromSubject(subjectWithNoPrincipals)); + + Subject subjectWithoutAuthenticatedPrincipal = new Subject(); + subjectWithoutAuthenticatedPrincipal.getPrincipals().add(new UsernamePrincipal("name1")); + assertNull("Should return null for a subject containing a principal that isn't an AuthenticatedPrincipal", + AuthenticatedPrincipal.getOptionalAuthenticatedPrincipalFromSubject(subjectWithoutAuthenticatedPrincipal)); + } + + public void testTooManyAuthenticatedPrincipalsInSubject() + { + final Subject subject = new Subject(); + subject.getPrincipals().add(new AuthenticatedPrincipal(new UsernamePrincipal("name1"))); + subject.getPrincipals().add(new AuthenticatedPrincipal(new UsernamePrincipal("name2"))); + + try + { + AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); + fail("Exception not thrown"); + } + catch (IllegalArgumentException iae) + { + // PASS + } + } + + private Subject createSubjectContainingAuthenticatedPrincipal() + { + final Principal other = new Principal() + { + public String getName() + { + return "otherprincipal"; + } + }; + + final Subject subject = new Subject(); + subject.getPrincipals().add(_authenticatedPrincipal); + subject.getPrincipals().add(other); + return subject; + } + + public void testEqualsAndHashcode() + { + AuthenticatedPrincipal user1principal1 = new AuthenticatedPrincipal(new UsernamePrincipal("user1")); + AuthenticatedPrincipal user1principal2 = new AuthenticatedPrincipal(new UsernamePrincipal("user1")); + + assertTrue(user1principal1.equals(user1principal1)); + assertTrue(user1principal1.equals(user1principal2)); + assertTrue(user1principal2.equals(user1principal1)); + + assertEquals(user1principal1.hashCode(), user1principal2.hashCode()); + } + + public void testEqualsAndHashcodeWithSameWrappedObject() + { + UsernamePrincipal wrappedPrincipal = new UsernamePrincipal("user1"); + AuthenticatedPrincipal user1principal1 = new AuthenticatedPrincipal(wrappedPrincipal); + AuthenticatedPrincipal user1principal2 = new AuthenticatedPrincipal(wrappedPrincipal); + + assertTrue(user1principal1.equals(user1principal1)); + assertTrue(user1principal1.equals(user1principal2)); + assertTrue(user1principal2.equals(user1principal1)); + + assertEquals(user1principal1.hashCode(), user1principal2.hashCode()); + } + + public void testEqualsWithDifferentUsernames() + { + AuthenticatedPrincipal user1principal1 = new AuthenticatedPrincipal(new UsernamePrincipal("user1")); + AuthenticatedPrincipal user1principal2 = new AuthenticatedPrincipal(new UsernamePrincipal("user2")); + + assertFalse(user1principal1.equals(user1principal2)); + assertFalse(user1principal2.equals(user1principal1)); + } + + public void testEqualsWithDisimilarObjects() + { + UsernamePrincipal wrappedPrincipal = new UsernamePrincipal("user1"); + AuthenticatedPrincipal authenticatedPrincipal = new AuthenticatedPrincipal(wrappedPrincipal); + + assertFalse(authenticatedPrincipal.equals(wrappedPrincipal)); + assertFalse(wrappedPrincipal.equals(authenticatedPrincipal)); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipalTestHelper.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipalTestHelper.java new file mode 100644 index 0000000000..e9d8d16fce --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticatedPrincipalTestHelper.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.server.security.auth; + +import java.security.Principal; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.Assert; + +/** + * Helper class for testing that sets of principals contain {@link AuthenticatedPrincipal}'s that wrap + * expected {@link Principal}'s. + */ +public class AuthenticatedPrincipalTestHelper +{ + public static void assertOnlyContainsWrapped(Principal wrappedPrincipal, Set principals) + { + assertOnlyContainsWrappedAndSecondaryPrincipals(wrappedPrincipal, Collections.emptySet(), principals); + } + + + public static void assertOnlyContainsWrappedAndSecondaryPrincipals( + Principal expectedWrappedPrincipal, + Set expectedSecondaryPrincipals, + Set actualPrincipals) + { + Assert.assertEquals("Principal set should contain one principal " + "but the principal set is: " + actualPrincipals, + 1 + expectedSecondaryPrincipals.size(), + actualPrincipals.size()); + + Set expectedSet = new HashSet(expectedSecondaryPrincipals); + expectedSet.add(new AuthenticatedPrincipal(expectedWrappedPrincipal)); + + Assert.assertEquals(expectedSet, actualPrincipals); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticationResultTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticationResultTest.java new file mode 100644 index 0000000000..a023cbdbb2 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/AuthenticationResultTest.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.auth; + +import static org.apache.qpid.server.security.auth.AuthenticatedPrincipalTestHelper.assertOnlyContainsWrapped; +import static org.apache.qpid.server.security.auth.AuthenticatedPrincipalTestHelper.assertOnlyContainsWrappedAndSecondaryPrincipals; +import static org.mockito.Mockito.mock; + +import java.security.Principal; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +public class AuthenticationResultTest extends TestCase +{ + public void testConstructWithAuthenticationStatusContinue() + { + AuthenticationResult authenticationResult = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.CONTINUE); + assertSame(AuthenticationResult.AuthenticationStatus.CONTINUE, authenticationResult.getStatus()); + assertTrue(authenticationResult.getPrincipals().isEmpty()); + } + + public void testConstructWithAuthenticationStatusError() + { + AuthenticationResult authenticationResult = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + assertSame(AuthenticationResult.AuthenticationStatus.ERROR, authenticationResult.getStatus()); + assertTrue(authenticationResult.getPrincipals().isEmpty()); + } + + public void testConstructWithAuthenticationStatusSuccessThrowsException() + { + try + { + new AuthenticationResult(AuthenticationResult.AuthenticationStatus.SUCCESS); + fail("Exception not thrown"); + } + catch(IllegalArgumentException e) + { + // PASS + } + } + + public void testConstructWithPrincipal() + { + Principal mainPrincipal = mock(Principal.class); + AuthenticationResult authenticationResult = new AuthenticationResult(mainPrincipal); + + assertOnlyContainsWrapped(mainPrincipal, authenticationResult.getPrincipals()); + assertSame(AuthenticationResult.AuthenticationStatus.SUCCESS, authenticationResult.getStatus()); + } + + public void testConstructWithNullPrincipalThrowsException() + { + try + { + new AuthenticationResult((Principal)null); + fail("Exception not thrown"); + } + catch(IllegalArgumentException e) + { + // pass + } + } + + public void testConstructWithSetOfPrincipals() + { + Principal mainPrincipal = mock(Principal.class); + Principal secondaryPrincipal = mock(Principal.class); + Set secondaryPrincipals = Collections.singleton(secondaryPrincipal); + + AuthenticationResult authenticationResult = new AuthenticationResult(mainPrincipal, secondaryPrincipals); + + assertOnlyContainsWrappedAndSecondaryPrincipals(mainPrincipal, secondaryPrincipals, authenticationResult.getPrincipals()); + assertSame(AuthenticationResult.AuthenticationStatus.SUCCESS, authenticationResult.getStatus()); + } + + public void testConstructWithSetOfPrincipalsDeDuplicatesMainPrincipal() + { + Principal mainPrincipal = mock(Principal.class); + Principal secondaryPrincipal = mock(Principal.class); + + Set secondaryPrincipalsContainingDuplicateOfMainPrincipal = new HashSet( + Arrays.asList(secondaryPrincipal, mainPrincipal)); + Set deDuplicatedSecondaryPrincipals = Collections.singleton(secondaryPrincipal); + + AuthenticationResult authenticationResult = new AuthenticationResult( + mainPrincipal, secondaryPrincipalsContainingDuplicateOfMainPrincipal); + + assertOnlyContainsWrappedAndSecondaryPrincipals(mainPrincipal, deDuplicatedSecondaryPrincipals, authenticationResult.getPrincipals()); + + assertSame(AuthenticationResult.AuthenticationStatus.SUCCESS, authenticationResult.getStatus()); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/TestPrincipalUtils.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/TestPrincipalUtils.java new file mode 100644 index 0000000000..ea6b40e3de --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/TestPrincipalUtils.java @@ -0,0 +1,49 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth; + +import javax.security.auth.Subject; + +import org.apache.qpid.server.security.group.GroupPrincipal; + +import java.security.Principal; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public class TestPrincipalUtils +{ + /** + * Creates a test subject, with exactly one {@link AuthenticatedPrincipal} and zero or more GroupPrincipals. + */ + public static Subject createTestSubject(final String username, final String... groups) + { + final Set principals = new HashSet(1 + groups.length); + principals.add(new AuthenticatedPrincipal(username)); + for (String group : groups) + { + principals.add(new GroupPrincipal(group)); + } + + return new Subject(true, principals, Collections.EMPTY_SET, Collections.EMPTY_SET); + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/UsernamePrincipalTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/UsernamePrincipalTest.java new file mode 100644 index 0000000000..5e025d3ca8 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/UsernamePrincipalTest.java @@ -0,0 +1,70 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth; + +import junit.framework.TestCase; + +/** + * Tests the UsernamePrincipal. + * + */ +public class UsernamePrincipalTest extends TestCase +{ + public void testEqualitySameObject() + { + final UsernamePrincipal principal = new UsernamePrincipal("string"); + assertTrue(principal.equals(principal)); + } + + public void testEqualitySameName() + { + final String string = "string"; + final UsernamePrincipal principal1 = new UsernamePrincipal(string); + final UsernamePrincipal principal2 = new UsernamePrincipal(string); + assertTrue(principal1.equals(principal2)); + } + + public void testEqualityEqualName() + { + final UsernamePrincipal principal1 = new UsernamePrincipal(new String("string")); + final UsernamePrincipal principal2 = new UsernamePrincipal(new String("string")); + assertTrue(principal1.equals(principal2)); + } + + public void testInequalityDifferentUserPrincipals() + { + UsernamePrincipal principal1 = new UsernamePrincipal("string1"); + UsernamePrincipal principal2 = new UsernamePrincipal("string2"); + assertFalse(principal1.equals(principal2)); + } + + public void testInequalityNonUserPrincipal() + { + UsernamePrincipal principal = new UsernamePrincipal("string"); + assertFalse(principal.equals(new String("string"))); + } + + public void testInequalityNull() + { + UsernamePrincipal principal = new UsernamePrincipal("string"); + assertFalse(principal.equals(null)); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabaseTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabaseTest.java index 33740af1e7..7b244e219e 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabaseTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/Base64MD5PasswordFilePrincipalDatabaseTest.java @@ -23,7 +23,7 @@ package org.apache.qpid.server.security.auth.database; import junit.framework.TestCase; import org.apache.commons.codec.binary.Base64; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.UsernamePrincipal; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.AccountNotFoundException; diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabaseTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabaseTest.java index b8601f0e5c..8e62324f7d 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabaseTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PlainPasswordFilePrincipalDatabaseTest.java @@ -22,7 +22,7 @@ package org.apache.qpid.server.security.auth.database; import junit.framework.TestCase; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.UsernamePrincipal; import javax.security.auth.login.AccountNotFoundException; import java.io.BufferedReader; diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java new file mode 100644 index 0000000000..f670d80ae8 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabase.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +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.IOException; +import java.security.Principal; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +public class PropertiesPrincipalDatabase implements PrincipalDatabase +{ + private Properties _users; + + private Map _saslServers; + + public PropertiesPrincipalDatabase(Properties users) + { + _users = users; + + _saslServers = new HashMap(); + + /** + * Create Authenticators for Properties Principal Database. + */ + + // 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 setPassword(Principal principal, PasswordCallback callback) throws IOException, AccountNotFoundException + { + if (principal == null) + { + throw new IllegalArgumentException("principal must not be null"); + } + + + + final String pwd = _users.getProperty(principal.getName()); + + if (pwd != null) + { + callback.setPassword(pwd.toCharArray()); + } + else + { + throw new AccountNotFoundException("No account found for principal " + principal); + } + } + + public boolean verifyPassword(String principal, char[] password) throws AccountNotFoundException + { + //fixme this is not correct as toCharArray is not safe based on the type of string. + char[] pwd = _users.getProperty(principal).toCharArray(); + + return compareCharArray(pwd, password); + } + + public boolean updatePassword(Principal principal, char[] password) throws AccountNotFoundException + { + return false; // updates denied + } + + public boolean createPrincipal(Principal principal, char[] 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; + } + + + public Map getMechanisms() + { + return _saslServers; + } + + public List getUsers() + { + return new LinkedList(); //todo + } + + public Principal getUser(String username) + { + if (_users.getProperty(username) != null) + { + return new UsernamePrincipal(username); + } + else + { + return null; + } + } + + public void reload() throws IOException + { + //No file to update from, so do nothing. + } + + @Override + public void setPasswordFile(String passwordFile) + { + throw new UnsupportedOperationException(); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java index 9dcd22c088..cfeb7c525b 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java @@ -20,26 +20,17 @@ */ package org.apache.qpid.server.security.auth.manager; +import static org.apache.qpid.server.security.auth.AuthenticatedPrincipalTestHelper.assertOnlyContainsWrapped; + import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; + import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class AnonymousAuthenticationManagerTest extends InternalBrokerBaseCase +public class AnonymousAuthenticationManagerTest extends QpidTestCase { - - private AuthenticationManager _manager = null; - - public void setUp() throws Exception - { - _manager = AnonymousAuthenticationManager.INSTANCE; - } - + private AuthenticationManager _manager = new AnonymousAuthenticationManager(); public void tearDown() throws Exception { @@ -49,29 +40,6 @@ public class AnonymousAuthenticationManagerTest extends InternalBrokerBaseCase } } - private ConfigurationPlugin getPlainDatabaseConfig() throws ConfigurationException - { - final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - xmlconfig.addProperty("pd-auth-manager.principal-database.class", PlainPasswordFilePrincipalDatabase.class.getName()); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - config.setConfiguration("security", xmlconfig); - return config; - } - - - public void testConfiguration() throws Exception - { - AuthenticationManager authenticationManager = - AnonymousAuthenticationManager.FACTORY.newInstance(getPlainDatabaseConfig()); - - assertNull("AnonymousAuthenticationManager unexpectedly created when not in config", authenticationManager); - } - public void testGetMechanisms() throws Exception { assertEquals("ANONYMOUS", _manager.getMechanisms()); @@ -102,7 +70,8 @@ public class AnonymousAuthenticationManagerTest extends InternalBrokerBaseCase assertEquals("Expected authentication to be successful", AuthenticationResult.AuthenticationStatus.SUCCESS, result.getStatus()); - assertNotNull("Subject should not be null", result.getSubject()); + + assertOnlyContainsWrapped(AnonymousAuthenticationManager.ANONYMOUS_PRINCIPAL, result.getPrincipals()); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java deleted file mode 100644 index efb8df3a38..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java +++ /dev/null @@ -1,304 +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.manager; - -import static org.mockito.Mockito.*; - -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.plugins.Plugin; -import org.apache.qpid.server.plugins.PluginManager; -import org.apache.qpid.server.security.SecurityManager.SecurityConfiguration; -import org.mockito.Mockito; - -import junit.framework.TestCase; - -public class AuthenticationManagerRegistryTest extends TestCase -{ - private static final Map> EMPTY_PLUGINMAP = Collections.emptyMap(); - - private PluginManager _pluginManager = Mockito.mock(PluginManager.class); - private ServerConfiguration _serverConfiguration = Mockito.mock(ServerConfiguration.class); - private SecurityConfiguration _securityConfiguration = Mockito.mock(SecurityConfiguration.class); - - private List _allCreatedAuthManagers = new ArrayList(); - - @Override - protected void setUp() throws Exception - { - super.setUp(); - - // Setup server configuration to return mock security config. - when(_serverConfiguration.getConfiguration(SecurityConfiguration.class.getName())).thenReturn(_securityConfiguration); - } - - @Override - protected void tearDown() throws Exception - { - try - { - verifyAllCreatedAuthManagersClosed(); - } - finally - { - super.tearDown(); - } - } - - public void testNoAuthenticationManagerFactoryPluginsFound() throws Exception - { - when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(EMPTY_PLUGINMAP); - try - { - new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - // PASS - assertEquals("No authentication manager factory plugins found. Check the desired authentication manager plugin has been placed in the plugins directory.", - ce.getMessage()); - } - } - - public void testSameAuthenticationManagerSpecifiedTwice() throws Exception - { - AuthenticationManagerPluginFactory myAuthManagerFactory = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); - - Map> pluginMap = createPluginMap(myAuthManagerFactory, myAuthManagerFactory); - - when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); - - try - { - new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - // PASS - assertEquals("Cannot configure more than one authentication manager of type " + myAuthManagerFactory.getPluginClass().getSimpleName() + ". Remove configuration for one of the authentication managers.", - ce.getMessage()); - } - } - - public void testMultipleAuthenticationManagersSpecifiedButNoDefaultSpecified() throws Exception - { - AuthenticationManagerPluginFactory myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); - AuthenticationManagerPluginFactory myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class); - - Map> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2); - - when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); - when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(null); - - try - { - new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - // PASS - assertEquals("If more than one authentication manager is configured a default MUST be specified.", - ce.getMessage()); - } - } - - public void testDefaultAuthenticationManagerNotKnown() throws Exception - { - String myDefaultAuthManagerSimpleClassName = "UnknownAuthenticationManager"; - - AuthenticationManagerPluginFactory myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); - AuthenticationManagerPluginFactory myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class); - - Map> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2); - - when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); - when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(myDefaultAuthManagerSimpleClassName); - - try - { - new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - // PASS - assertTrue("Unexpected message " + ce.getMessage(), - ce.getMessage().startsWith("No authentication managers configured of type " + myDefaultAuthManagerSimpleClassName + " which is specified as the default")); - } - } - - public void testPortMappedToUnknownAuthenticationManager() throws Exception - { - String myDefaultAuthManagerSimpleClassName = "UnknownAuthenticationManager"; - int portNumber = 1234; - - AuthenticationManagerPluginFactory myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); - - Map> pluginMap = createPluginMap(myAuthManagerFactory1); - - when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); - when(_serverConfiguration.getPortAuthenticationMappings()).thenReturn(Collections.singletonMap(portNumber, myDefaultAuthManagerSimpleClassName)); - - try - { - new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - // PASS - assertEquals("Unknown authentication manager class " + myDefaultAuthManagerSimpleClassName + " configured for port " + portNumber, ce.getMessage()); - } - } - - public void testGetAuthenticationManagerForInetSocketAddress() throws Exception - { - AuthenticationManagerPluginFactory myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); - Map> pluginMap = createPluginMap(myAuthManagerFactory1); - - when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); - - AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); - - AuthenticationManager authenticationManager = registry.getAuthenticationManager(new InetSocketAddress(1234)); - assertEquals("TestAuthenticationManager1", authenticationManager.getMechanisms()); - - registry.close(); - } - - public void testGetAuthenticationManagerForNonInetSocketAddress() throws Exception - { - AuthenticationManagerPluginFactory myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); - Map> pluginMap = createPluginMap(myAuthManagerFactory1); - - when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); - - AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); - - AuthenticationManager authenticationManager = registry.getAuthenticationManager(mock(SocketAddress.class)); - assertEquals("TestAuthenticationManager1", authenticationManager.getMechanisms()); - - registry.close(); - } - - public void testGetAuthenticationManagerWithMultipleAuthenticationManager() throws Exception - { - AuthenticationManagerPluginFactory myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); - AuthenticationManagerPluginFactory myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class); - Map> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2); - - String defaultAuthManger = myAuthManagerFactory1.getPluginName(); - int unmappedPortNumber = 1234; - int mappedPortNumber = 1235; - String mappedAuthManager = myAuthManagerFactory2.getPluginName(); - - when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); - when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(defaultAuthManger); - when(_serverConfiguration.getPortAuthenticationMappings()).thenReturn(Collections.singletonMap(mappedPortNumber, mappedAuthManager)); - - AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); - - AuthenticationManager authenticationManager1 = registry.getAuthenticationManager(new InetSocketAddress(unmappedPortNumber)); - assertEquals("TestAuthenticationManager1", authenticationManager1.getMechanisms()); - - AuthenticationManager authenticationManager2 = registry.getAuthenticationManager(new InetSocketAddress(mappedPortNumber)); - assertEquals("TestAuthenticationManager2", authenticationManager2.getMechanisms()); - - registry.close(); - } - - public void testAuthenticationManagersAreClosed() throws Exception - { - AuthenticationManagerPluginFactory myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); - AuthenticationManagerPluginFactory myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class); - Map> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2); - - String defaultAuthManger = myAuthManagerFactory1.getPluginName(); - when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); - when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(defaultAuthManger); - - AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); - - registry.close(); - } - - private AuthenticationManagerPluginFactory newMockFactoryProducingMockAuthManagerImplementing(Class authManagerClazz) - throws ConfigurationException - { - AuthenticationManager myAuthManager = mock(authManagerClazz); - when(myAuthManager.getMechanisms()).thenReturn(authManagerClazz.getSimpleName()); // used to verify the getAuthenticationManagerFor returns expected impl. - - AuthenticationManagerPluginFactory myAuthManagerFactory = mock(AuthenticationManagerPluginFactory.class); - when(myAuthManagerFactory.getPluginClass()).thenReturn(myAuthManager.getClass()); - when(myAuthManagerFactory.getPluginName()).thenReturn(myAuthManager.getClass().getSimpleName()); - when(myAuthManagerFactory.newInstance(_securityConfiguration)).thenReturn(myAuthManager); - - _allCreatedAuthManagers.add(myAuthManager); - return myAuthManagerFactory; - } - - private Map> createPluginMap( - AuthenticationManagerPluginFactory myAuthManagerFactory) - { - return createPluginMap(myAuthManagerFactory, null); - } - - private Map> createPluginMap( - AuthenticationManagerPluginFactory authManagerFactory1, - AuthenticationManagerPluginFactory authManagerFactory2) - { - Map> pluginMap = new HashMap>(); - pluginMap.put("config.path.unused1", authManagerFactory1); - if (authManagerFactory2 != null) - { - pluginMap.put("config.path.unused2", authManagerFactory2); - } - return pluginMap; - } - - private void verifyAllCreatedAuthManagersClosed() - { - for (Iterator iterator = _allCreatedAuthManagers.iterator(); iterator.hasNext();) - { - AuthenticationManager authenticationManager = (AuthenticationManager) iterator.next(); - verify(authenticationManager).close(); - } - } - - private interface TestAuthenticationManager1 extends AuthenticationManager - { - } - - private interface TestAuthenticationManager2 extends AuthenticationManager - { - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/Base64MD5PasswordFileAuthenticationManagerFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/Base64MD5PasswordFileAuthenticationManagerFactoryTest.java new file mode 100644 index 0000000000..04e09e073f --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/Base64MD5PasswordFileAuthenticationManagerFactoryTest.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.auth.manager; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.security.auth.database.Base64MD5PasswordFilePrincipalDatabase; + +public class Base64MD5PasswordFileAuthenticationManagerFactoryTest extends TestCase +{ + AuthenticationManagerFactory _factory = new Base64MD5PasswordFileAuthenticationManagerFactory(); + private Map _configuration = new HashMap(); + private File _emptyPasswordFile; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _emptyPasswordFile = File.createTempFile(getName(), "passwd"); + _emptyPasswordFile.deleteOnExit(); + } + + public void testBase64MD5InstanceCreated() throws Exception + { + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_TYPE, Base64MD5PasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, _emptyPasswordFile.getAbsolutePath()); + + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNotNull(manager); + assertTrue(manager instanceof PrincipalDatabaseAuthenticationManager); + assertTrue(((PrincipalDatabaseAuthenticationManager)manager).getPrincipalDatabase() instanceof Base64MD5PasswordFilePrincipalDatabase); + } + + public void testPasswordFileNotFound() throws Exception + { + //delete the file + _emptyPasswordFile.delete(); + + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_TYPE, Base64MD5PasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, _emptyPasswordFile.getAbsolutePath()); + + try + { + _factory.createInstance(_configuration); + } + catch (RuntimeException re) + { + assertTrue(re.getCause() instanceof FileNotFoundException); + } + } + + public void testReturnsNullWhenNoConfig() throws Exception + { + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNull(manager); + } + + public void testReturnsNullWhenConfigForOtherAuthManagerType() throws Exception + { + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_TYPE, "other-auth-manager"); + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNull(manager); + } + + public void testReturnsNullWhenConfigForPlainPDImplementationNoPasswordFileValueSpecified() throws Exception + { + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_TYPE, Base64MD5PasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNull(manager); + } + + @Override + protected void tearDown() throws Exception + { + try + { + if (_emptyPasswordFile == null && _emptyPasswordFile.exists()) + { + _emptyPasswordFile.delete(); + } + } + finally + { + super.tearDown(); + } + } +} \ No newline at end of file diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java index c1a55ef2ad..a66d73c47d 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java @@ -18,58 +18,18 @@ */ package org.apache.qpid.server.security.auth.manager; +import static org.apache.qpid.server.security.auth.AuthenticatedPrincipalTestHelper.assertOnlyContainsWrapped; + import javax.security.auth.x500.X500Principal; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; + import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class ExternalAuthenticationManagerTest extends InternalBrokerBaseCase +public class ExternalAuthenticationManagerTest extends QpidTestCase { - - private AuthenticationManager _manager = null; - - public void setUp() throws Exception - { - _manager = ExternalAuthenticationManager.INSTANCE; - } - - - public void tearDown() throws Exception - { - if(_manager != null) - { - _manager = null; - } - } - - private ConfigurationPlugin getPlainDatabaseConfig() throws ConfigurationException - { - final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - xmlconfig.addProperty("pd-auth-manager.principal-database.class", PlainPasswordFilePrincipalDatabase.class.getName()); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - config.setConfiguration("security", xmlconfig); - return config; - } - - - public void testConfiguration() throws Exception - { - AuthenticationManager authenticationManager = - ExternalAuthenticationManager.FACTORY.newInstance(getPlainDatabaseConfig()); - - assertNull("ExternalAuthenticationManager unexpectedly created when not in config", authenticationManager); - } + private AuthenticationManager _manager = new ExternalAuthenticationManager(); public void testGetMechanisms() throws Exception { @@ -103,12 +63,12 @@ public class ExternalAuthenticationManagerTest extends InternalBrokerBaseCase assertEquals("Expected authentication to be successful", AuthenticationResult.AuthenticationStatus.SUCCESS, result.getStatus()); - assertEquals("Expected principal to be unchanged", - principal, - result.getSubject().getPrincipals().iterator().next()); + + assertOnlyContainsWrapped(principal, result.getPrincipals()); saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", null); result = _manager.authenticate(saslServer, new byte[0]); + assertNotNull(result); assertEquals("Expected authentication to be unsuccessful", AuthenticationResult.AuthenticationStatus.ERROR, diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PlainPasswordFileAuthenticationManagerFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PlainPasswordFileAuthenticationManagerFactoryTest.java new file mode 100644 index 0000000000..d428f8b211 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PlainPasswordFileAuthenticationManagerFactoryTest.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.auth.manager; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; + +public class PlainPasswordFileAuthenticationManagerFactoryTest extends TestCase +{ + AuthenticationManagerFactory _factory = new PlainPasswordFileAuthenticationManagerFactory(); + private Map _configuration = new HashMap(); + private File _emptyPasswordFile; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _emptyPasswordFile = File.createTempFile(getName(), "passwd"); + _emptyPasswordFile.deleteOnExit(); + } + + public void testPlainInstanceCreated() throws Exception + { + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_TYPE, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, _emptyPasswordFile.getAbsolutePath()); + + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNotNull(manager); + assertTrue(manager instanceof PrincipalDatabaseAuthenticationManager); + assertTrue(((PrincipalDatabaseAuthenticationManager)manager).getPrincipalDatabase() instanceof PlainPasswordFilePrincipalDatabase); + } + + public void testPasswordFileNotFound() throws Exception + { + //delete the file + _emptyPasswordFile.delete(); + + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_TYPE, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, _emptyPasswordFile.getAbsolutePath()); + + try + { + _factory.createInstance(_configuration); + } + catch (RuntimeException re) + { + assertTrue(re.getCause() instanceof FileNotFoundException); + } + } + + public void testReturnsNullWhenNoConfig() throws Exception + { + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNull(manager); + } + + public void testReturnsNullWhenConfigForOtherAuthManagerType() throws Exception + { + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_TYPE, "other-auth-manager"); + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNull(manager); + } + + public void testReturnsNullWhenConfigForPlainPDImplementationNoPasswordFileValueSpecified() throws Exception + { + _configuration.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_TYPE, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNull(manager); + } + + @Override + protected void tearDown() throws Exception + { + try + { + if (_emptyPasswordFile == null && _emptyPasswordFile.exists()) + { + _emptyPasswordFile.delete(); + } + } + finally + { + super.tearDown(); + } + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java index 47c189e4fa..1ae667804a 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java @@ -20,132 +20,92 @@ */ package org.apache.qpid.server.security.auth.manager; -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; +import static org.apache.qpid.server.security.auth.AuthenticatedPrincipalTestHelper.assertOnlyContainsWrapped; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.security.auth.AuthenticationResult; -import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; -import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import java.security.Provider; +import java.security.Security; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; -import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.security.Provider; -import java.security.Security; +import javax.security.sasl.SaslServerFactory; + +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +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.UsernamePasswordInitialiser; +import org.apache.qpid.test.utils.QpidTestCase; /** - * * Tests the public methods of PrincipalDatabaseAuthenticationManager. * */ -public class PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBaseCase +public class PrincipalDatabaseAuthenticationManagerTest extends QpidTestCase { + private static final String MOCK_MECH_NAME = "MOCK-MECH-NAME"; + private static final UsernamePrincipal PRINCIPAL = new UsernamePrincipal("guest"); + private AuthenticationManager _manager = null; // Class under test - private String TEST_USERNAME = "guest"; - private String TEST_PASSWORD = "guest"; + private PrincipalDatabase _principalDatabase; - /** - * @see org.apache.qpid.server.util.InternalBrokerBaseCase#tearDown() - */ @Override public void tearDown() throws Exception { - super.tearDown(); if (_manager != null) { _manager.close(); } + super.tearDown(); } - /** - * @see org.apache.qpid.server.util.InternalBrokerBaseCase#setUp() - */ - @Override - public void setUp() throws Exception + private void setupMocks() throws Exception { - super.setUp(); - - final String passwdFilename = createPasswordFile().getCanonicalPath(); - final ConfigurationPlugin config = getConfig(PlainPasswordFilePrincipalDatabase.class.getName(), - "passwordFile", passwdFilename); + _principalDatabase = mock(PrincipalDatabase.class); - _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(config); - } + AuthenticationProviderInitialiser _mockMechInitialiser = mock(AuthenticationProviderInitialiser.class); + Map _initialisers = Collections.singletonMap(MOCK_MECH_NAME, _mockMechInitialiser); - /** - * Tests where the case where the config specifies a PD implementation - * that is not found. - */ - public void testPrincipalDatabaseImplementationNotFound() throws Exception - { - try - { - _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(getConfig("not.Found", null, null)); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - // PASS - } - } + when(_principalDatabase.getMechanisms()).thenReturn(_initialisers); - /** - * Tests where the case where the config specifies a PD implementation - * of the wrong type. - */ - public void testPrincipalDatabaseImplementationWrongType() throws Exception - { - try - { - _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(getConfig(String.class.getName(), null, null)); // Not a PrincipalDatabase implementation - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - // PASS - } + _manager = new PrincipalDatabaseAuthenticationManager(_principalDatabase); + _manager.initialise(); } - /** - * Tests the case where a setter with the desired name cannot be found. - */ - public void testPrincipalDatabaseSetterNotFound() throws Exception + private void setupMocksWithInitialiser() throws Exception { - try - { - _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(getConfig(PlainPasswordFilePrincipalDatabase.class.getName(), "noMethod", "test")); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) - { - // PASS - } - } + _principalDatabase = mock(PrincipalDatabase.class); - /** - * QPID-1347. Make sure the exception message and stack trace is reasonable for an absent password file. - */ - public void testPrincipalDatabaseThrowsSetterFileNotFound() throws Exception - { - try - { - _manager = PrincipalDatabaseAuthenticationManager.FACTORY.newInstance(getConfig(PlainPasswordFilePrincipalDatabase.class.getName(), "passwordFile", "/not/found")); - fail("Exception not thrown"); - } - catch (ConfigurationException ce) + UsernamePasswordInitialiser usernamePasswordInitialiser = new UsernamePasswordInitialiser() { - // PASS - assertNotNull("Expected an underlying cause", ce.getCause()); - assertEquals(FileNotFoundException.class, ce.getCause().getClass()); - } + @Override + public Class getServerFactoryClassForJCARegistration() + { + return MySaslServerFactory.class; + } + + @Override + public String getMechanismName() + { + return MOCK_MECH_NAME; + } + }; + + Map initialisers = new HashMap(); + initialisers.put(MOCK_MECH_NAME, usernamePasswordInitialiser); + + when(_principalDatabase.getMechanisms()).thenReturn(initialisers); + + usernamePasswordInitialiser.initialise(_principalDatabase); + + _manager = new PrincipalDatabaseAuthenticationManager(_principalDatabase); + _manager.initialise(); } /** @@ -153,11 +113,16 @@ public class PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa */ public void testRegisteredMechanisms() throws Exception { + //Ensure we haven't registered anything yet (though this would really indicate a prior test failure!) + Provider qpidProvider = Security.getProvider(AuthenticationManager.PROVIDER_NAME); + assertNull(qpidProvider); + + setupMocksWithInitialiser(); + assertNotNull(_manager.getMechanisms()); - // relies on those mechanisms attached to PropertiesPrincipalDatabaseManager - assertEquals("AMQPLAIN PLAIN CRAM-MD5", _manager.getMechanisms()); + assertEquals(MOCK_MECH_NAME, _manager.getMechanisms()); - Provider qpidProvider = Security.getProvider(PrincipalDatabaseAuthenticationManager.PROVIDER_NAME); + qpidProvider = Security.getProvider(AuthenticationManager.PROVIDER_NAME); assertNotNull(qpidProvider); } @@ -167,96 +132,103 @@ public class PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa */ public void testSaslMechanismCreation() throws Exception { - SaslServer server = _manager.createSaslServer("CRAM-MD5", "localhost", null); + setupMocksWithInitialiser(); + + SaslServer server = _manager.createSaslServer(MOCK_MECH_NAME, "localhost", null); assertNotNull(server); // Merely tests the creation of the mechanism. Mechanisms themselves are tested // by their own tests. } - + /** * Tests that the authenticate method correctly interprets an * authentication success. - * + * */ public void testSaslAuthenticationSuccess() throws Exception { + setupMocks(); + SaslServer testServer = createTestSaslServer(true, false); - + AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes()); - final Subject subject = result.getSubject(); - assertTrue(subject.getPrincipals().contains(new UsernamePrincipal("guest"))); + + assertOnlyContainsWrapped(PRINCIPAL, result.getPrincipals()); assertEquals(AuthenticationStatus.SUCCESS, result.getStatus()); } /** - * + * * Tests that the authenticate method correctly interprets an * authentication not complete. - * + * */ public void testSaslAuthenticationNotCompleted() throws Exception { + setupMocks(); + SaslServer testServer = createTestSaslServer(false, false); - + AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes()); - assertNull(result.getSubject()); + assertEquals("Principals was not expected size", 0, result.getPrincipals().size()); + assertEquals(AuthenticationStatus.CONTINUE, result.getStatus()); } /** - * + * * Tests that the authenticate method correctly interprets an * authentication error. - * + * */ public void testSaslAuthenticationError() throws Exception { + setupMocks(); + SaslServer testServer = createTestSaslServer(false, true); - + AuthenticationResult result = _manager.authenticate(testServer, "12345".getBytes()); - assertNull(result.getSubject()); + assertEquals("Principals was not expected size", 0, result.getPrincipals().size()); assertEquals(AuthenticationStatus.ERROR, result.getStatus()); } - /** - * Tests that the authenticate method correctly interprets an - * authentication success. - * - */ public void testNonSaslAuthenticationSuccess() throws Exception { + setupMocks(); + + when(_principalDatabase.verifyPassword("guest", "guest".toCharArray())).thenReturn(true); + AuthenticationResult result = _manager.authenticate("guest", "guest"); - final Subject subject = result.getSubject(); - assertFalse("Subject should not be set read-only", subject.isReadOnly()); - assertTrue(subject.getPrincipals().contains(new UsernamePrincipal("guest"))); + assertOnlyContainsWrapped(PRINCIPAL, result.getPrincipals()); assertEquals(AuthenticationStatus.SUCCESS, result.getStatus()); } - /** - * Tests that the authenticate method correctly interprets an - * authentication success. - * - */ public void testNonSaslAuthenticationNotCompleted() throws Exception { + setupMocks(); + + when(_principalDatabase.verifyPassword("guest", "wrongpassword".toCharArray())).thenReturn(false); + AuthenticationResult result = _manager.authenticate("guest", "wrongpassword"); - assertNull(result.getSubject()); + assertEquals("Principals was not expected size", 0, result.getPrincipals().size()); assertEquals(AuthenticationStatus.CONTINUE, result.getStatus()); } - + /** * Tests the ability to de-register the provider. */ public void testClose() throws Exception { - assertEquals("AMQPLAIN PLAIN CRAM-MD5", _manager.getMechanisms()); - assertNotNull(Security.getProvider(PrincipalDatabaseAuthenticationManager.PROVIDER_NAME)); + setupMocksWithInitialiser(); + + assertEquals(MOCK_MECH_NAME, _manager.getMechanisms()); + assertNotNull(Security.getProvider(AuthenticationManager.PROVIDER_NAME)); _manager.close(); // Check provider has been removed. assertNull(_manager.getMechanisms()); - assertNull(Security.getProvider(PrincipalDatabaseAuthenticationManager.PROVIDER_NAME)); + assertNull(Security.getProvider(AuthenticationManager.PROVIDER_NAME)); _manager = null; } @@ -265,94 +237,90 @@ public class PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa */ private SaslServer createTestSaslServer(final boolean complete, final boolean throwSaslException) { - return new SaslServer() - { - public String getMechanismName() - { - return null; - } + return new MySaslServer(throwSaslException, complete); + } - public byte[] evaluateResponse(byte[] response) throws SaslException - { - if (throwSaslException) - { - throw new SaslException("Mocked exception"); - } - return null; - } + public static final class MySaslServer implements SaslServer + { + private final boolean _throwSaslException; + private final boolean _complete; - public boolean isComplete() - { - return complete; - } + public MySaslServer() + { + this(false, true); + } - public String getAuthorizationID() - { - return complete ? "guest" : null; - } + private MySaslServer(boolean throwSaslException, boolean complete) + { + _throwSaslException = throwSaslException; + _complete = complete; + } - public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException - { - return null; - } + public String getMechanismName() + { + return null; + } - public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException + public byte[] evaluateResponse(byte[] response) throws SaslException + { + if (_throwSaslException) { - return null; + throw new SaslException("Mocked exception"); } + return null; + } - public Object getNegotiatedProperty(String propName) - { - return null; - } + public boolean isComplete() + { + return _complete; + } - public void dispose() throws SaslException - { - } - }; - } + public String getAuthorizationID() + { + return _complete ? "guest" : null; + } - private ConfigurationPlugin getConfig(final String clazz, final String argName, final String argValue) throws Exception - { - final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration(); + public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException + { + return null; + } - XMLConfiguration xmlconfig = new XMLConfiguration(); - xmlconfig.addProperty("pd-auth-manager.principal-database.class", clazz); + public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException + { + return null; + } - if (argName != null) + public Object getNegotiatedProperty(String propName) { - xmlconfig.addProperty("pd-auth-manager.principal-database.attributes.attribute.name", argName); - xmlconfig.addProperty("pd-auth-manager.principal-database.attributes.attribute.value", argValue); + return null; } - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - config.setConfiguration("security", xmlconfig); - return config; + public void dispose() throws SaslException + { + } } - private File createPasswordFile() throws Exception + public static class MySaslServerFactory implements SaslServerFactory { - BufferedWriter writer = null; - try - { - File testFile = File.createTempFile(this.getClass().getName(),"tmp"); - testFile.deleteOnExit(); - - writer = new BufferedWriter(new FileWriter(testFile)); - writer.write(TEST_USERNAME + ":" + TEST_PASSWORD); - writer.newLine(); - - return testFile; - - } - finally + @Override + public SaslServer createSaslServer(String mechanism, String protocol, + String serverName, Map props, CallbackHandler cbh) + throws SaslException { - if (writer != null) + if (MOCK_MECH_NAME.equals(mechanism)) { - writer.close(); + return new MySaslServer(); } + else + { + return null; + } + } + + @Override + public String[] getMechanismNames(Map props) + { + return new String[]{MOCK_MECH_NAME}; } } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java new file mode 100644 index 0000000000..1424bee611 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.auth.manager; + +import java.util.HashMap; +import java.util.Map; + + +import junit.framework.TestCase; + +public class SimpleLDAPAuthenticationManagerFactoryTest extends TestCase +{ + private SimpleLDAPAuthenticationManagerFactory _factory = new SimpleLDAPAuthenticationManagerFactory(); + private Map _configuration = new HashMap(); + + public void testInstanceCreated() throws Exception + { + _configuration.put(SimpleLDAPAuthenticationManagerFactory.ATTRIBUTE_TYPE, SimpleLDAPAuthenticationManagerFactory.PROVIDER_TYPE); + _configuration.put("providerUrl", "ldaps://example.com:636/"); + _configuration.put("searchContext", "dc=example"); + + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNotNull(manager); + } + + public void testReturnsNullWhenNoConfig() throws Exception + { + AuthenticationManager manager = _factory.createInstance(_configuration); + assertNull(manager); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java index c0c55de92a..52b525dd80 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java @@ -20,20 +20,26 @@ */ package org.apache.qpid.server.security.auth.rmi; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.security.Principal; +import java.util.regex.Pattern; + +import javax.security.auth.Subject; + import junit.framework.TestCase; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.auth.AuthenticationResult; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; - -import javax.management.remote.JMXPrincipal; -import javax.security.auth.Subject; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; -import java.net.InetSocketAddress; -import java.util.Collections; +import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; +import org.apache.qpid.server.security.SecurityManager; /** * Tests the RMIPasswordAuthenticator and its collaboration with the AuthenticationManager. @@ -41,36 +47,35 @@ import java.util.Collections; */ public class RMIPasswordAuthenticatorTest extends TestCase { - private final String USERNAME = "guest"; - private final String PASSWORD = "guest"; + private static final String USERNAME = "guest"; + private static final String PASSWORD = "password"; + + private final Broker _broker = mock(Broker.class); + private final SecurityManager _securityManager = mock(SecurityManager.class); + private final Subject _loginSubject = new Subject(); + private final String[] _credentials = new String[] {USERNAME, PASSWORD}; + private RMIPasswordAuthenticator _rmipa; - private String[] _credentials; + + private SubjectCreator _usernamePasswordOkaySuvjectCreator = createMockSubjectCreator(true, null); + private SubjectCreator _badPasswordSubjectCreator = createMockSubjectCreator(false, null); protected void setUp() throws Exception { - _rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(5672)); - - _credentials = new String[] {USERNAME, PASSWORD}; + when(_broker.getSecurityManager()).thenReturn(_securityManager); + _rmipa = new RMIPasswordAuthenticator(_broker, new InetSocketAddress(8999)); } /** - * Tests a successful authentication. Ensures that a populated read-only subject it returned. + * Tests a successful authentication. Ensures that the expected subject is returned. */ public void testAuthenticationSuccess() { - final Subject expectedSubject = new Subject(true, - Collections.singleton(new JMXPrincipal(USERNAME)), - Collections.EMPTY_SET, - Collections.EMPTY_SET); - - _rmipa.setAuthenticationManager(createTestAuthenticationManager(true, null)); - + when(_broker.getSubjectCreator(any(SocketAddress.class))).thenReturn(_usernamePasswordOkaySuvjectCreator); + when(_securityManager.accessManagement()).thenReturn(true); Subject newSubject = _rmipa.authenticate(_credentials); - assertTrue("Subject must be readonly", newSubject.isReadOnly()); - assertTrue("Returned subject does not equal expected value", - newSubject.equals(expectedSubject)); - + assertSame("Subject must be unchanged", _loginSubject, newSubject); } /** @@ -78,7 +83,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase */ public void testUsernameOrPasswordInvalid() { - _rmipa.setAuthenticationManager(createTestAuthenticationManager(false, null)); + when(_broker.getSubjectCreator(any(SocketAddress.class))).thenReturn(_badPasswordSubjectCreator); try { @@ -89,17 +94,31 @@ public class RMIPasswordAuthenticatorTest extends TestCase { assertEquals("Unexpected exception message", RMIPasswordAuthenticator.INVALID_CREDENTIALS, se.getMessage()); + } + } + + public void testAuthorisationFailure() + { + when(_broker.getSubjectCreator(any(SocketAddress.class))).thenReturn(_usernamePasswordOkaySuvjectCreator); + when(_securityManager.accessManagement()).thenReturn(false); + try + { + _rmipa.authenticate(_credentials); + fail("Exception not thrown"); + } + catch (SecurityException se) + { + assertEquals("Unexpected exception message", + RMIPasswordAuthenticator.USER_NOT_AUTHORISED_FOR_MANAGEMENT, se.getMessage()); } } - /** - * Tests case where authentication system itself fails. - */ - public void testAuthenticationFailure() + public void testSubjectCreatorInternalFailure() { final Exception mockAuthException = new Exception("Mock Auth system failure"); - _rmipa.setAuthenticationManager(createTestAuthenticationManager(false, mockAuthException)); + SubjectCreator subjectCreator = createMockSubjectCreator(false, mockAuthException); + when(_broker.getSubjectCreator(any(SocketAddress.class))).thenReturn(subjectCreator); try { @@ -112,13 +131,13 @@ public class RMIPasswordAuthenticatorTest extends TestCase } } - /** * Tests case where authentication manager is not set. */ - public void testNullAuthenticationManager() throws Exception + public void testNullSubjectCreator() throws Exception { - _rmipa.setAuthenticationManager(null); + when(_broker.getSubjectCreator(any(SocketAddress.class))).thenReturn(null); + try { _rmipa.authenticate(_credentials); @@ -126,8 +145,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase } catch (SecurityException se) { - assertEquals("Unexpected exception message", - RMIPasswordAuthenticator.UNABLE_TO_LOOKUP, se.getMessage()); + assertTrue("Unexpected exception message", Pattern.matches("Can't get subject creator for .*:8999", se.getMessage())); } } @@ -155,11 +173,13 @@ public class RMIPasswordAuthenticatorTest extends TestCase */ public void testWithIllegalNumberOfArguments() { + String[] credentials; + // Test handling of incorrect number of credentials try { - _credentials = new String[]{USERNAME, PASSWORD, PASSWORD}; - _rmipa.authenticate(_credentials); + credentials = new String[]{USERNAME, PASSWORD, PASSWORD}; + _rmipa.authenticate(credentials); fail("SecurityException expected due to supplying wrong number of credentials"); } catch (SecurityException se) @@ -172,8 +192,8 @@ public class RMIPasswordAuthenticatorTest extends TestCase try { //send a null array - _credentials = null; - _rmipa.authenticate(_credentials); + credentials = null; + _rmipa.authenticate(credentials); fail("SecurityException expected due to not supplying an array of credentials"); } catch (SecurityException se) @@ -185,8 +205,8 @@ public class RMIPasswordAuthenticatorTest extends TestCase try { //send a null password - _credentials = new String[]{USERNAME, null}; - _rmipa.authenticate(_credentials); + credentials = new String[]{USERNAME, null}; + _rmipa.authenticate(credentials); fail("SecurityException expected due to sending a null password"); } catch (SecurityException se) @@ -198,8 +218,8 @@ public class RMIPasswordAuthenticatorTest extends TestCase try { //send a null username - _credentials = new String[]{null, PASSWORD}; - _rmipa.authenticate(_credentials); + credentials = new String[]{null, PASSWORD}; + _rmipa.authenticate(credentials); fail("SecurityException expected due to sending a null username"); } catch (SecurityException se) @@ -209,55 +229,30 @@ public class RMIPasswordAuthenticatorTest extends TestCase } } - private AuthenticationManager createTestAuthenticationManager(final boolean successfulAuth, final Exception exception) + private SubjectCreator createMockSubjectCreator(final boolean successfulAuth, final Exception exception) { - return new AuthenticationManager() + SubjectCreator subjectCreator = mock(SubjectCreator.class); + + SubjectAuthenticationResult subjectAuthenticationResult; + + if (exception != null) { + + subjectAuthenticationResult = new SubjectAuthenticationResult( + new AuthenticationResult(AuthenticationStatus.ERROR, exception)); + } + else if (successfulAuth) { - public void configure(ConfigurationPlugin config) - { - throw new UnsupportedOperationException(); - } - - public void initialise() - { - throw new UnsupportedOperationException(); - } - - public void close() - { - throw new UnsupportedOperationException(); - } - - public String getMechanisms() - { - throw new UnsupportedOperationException(); - } - - public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException - { - throw new UnsupportedOperationException(); - } - - public AuthenticationResult authenticate(SaslServer server, byte[] response) - { - throw new UnsupportedOperationException(); - } - - public AuthenticationResult authenticate(String username, String password) - { - if (exception != null) { - return new AuthenticationResult(AuthenticationStatus.ERROR, exception); - } - else if (successfulAuth) - { - return new AuthenticationResult(new Subject()); - } - else - { - return new AuthenticationResult(AuthenticationStatus.CONTINUE); - } - } - - }; + + subjectAuthenticationResult = new SubjectAuthenticationResult( + new AuthenticationResult(mock(Principal.class)), _loginSubject); + } + else + { + subjectAuthenticationResult = new SubjectAuthenticationResult(new AuthenticationResult(AuthenticationStatus.CONTINUE)); + } + + when(subjectCreator.authenticate(anyString(), anyString())).thenReturn(subjectAuthenticationResult); + + return subjectCreator; } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipalTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipalTest.java deleted file mode 100644 index 076b7c9248..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipalTest.java +++ /dev/null @@ -1,86 +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.sasl; - -import junit.framework.TestCase; - -public class GroupPrincipalTest extends TestCase -{ - public void testGetName() - { - final GroupPrincipal principal = new GroupPrincipal("group"); - assertEquals("group", principal.getName()); - } - - public void testAddRejected() - { - final GroupPrincipal principal = new GroupPrincipal("group"); - final UsernamePrincipal user = new UsernamePrincipal("name"); - - try - { - principal.addMember(user); - fail("Exception not thrown"); - } - catch (UnsupportedOperationException uso) - { - // PASS - } - } - - public void testEqualitySameName() - { - final String string = "string"; - final GroupPrincipal principal1 = new GroupPrincipal(string); - final GroupPrincipal principal2 = new GroupPrincipal(string); - assertTrue(principal1.equals(principal2)); - } - - public void testEqualityEqualName() - { - final GroupPrincipal principal1 = new GroupPrincipal(new String("string")); - final GroupPrincipal principal2 = new GroupPrincipal(new String("string")); - assertTrue(principal1.equals(principal2)); - } - - public void testInequalityDifferentGroupPrincipals() - { - GroupPrincipal principal1 = new GroupPrincipal("string1"); - GroupPrincipal principal2 = new GroupPrincipal("string2"); - assertFalse(principal1.equals(principal2)); - } - - public void testInequalityNonGroupPrincipal() - { - GroupPrincipal principal = new GroupPrincipal("string"); - assertFalse(principal.equals(new UsernamePrincipal("string"))); - } - - public void testInequalityNull() - { - GroupPrincipal principal = new GroupPrincipal("string"); - assertFalse(principal.equals(null)); - } - - - - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalDatabase.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalDatabase.java index 8c7f3ad6ef..f94d8ddfc3 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalDatabase.java +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalDatabase.java @@ -86,4 +86,10 @@ public class TestPrincipalDatabase implements PrincipalDatabase // TODO Auto-generated method stub } + @Override + public void setPasswordFile(String passwordFile) throws IOException + { + // TODO Auto-generated method stub + } + } diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalUtils.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalUtils.java deleted file mode 100644 index 7ce03eaa79..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/TestPrincipalUtils.java +++ /dev/null @@ -1,48 +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.sasl; - -import javax.security.auth.Subject; -import java.security.Principal; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -public class TestPrincipalUtils -{ - - /** - * Creates a test subject, with exactly one UsernamePrincipal and zero or more GroupPrincipals. - */ - public static Subject createTestSubject(final String username, final String... groups) - { - final Set principals = new HashSet(1 + groups.length); - principals.add(new UsernamePrincipal(username)); - for (String group : groups) - { - principals.add(new GroupPrincipal(group)); - } - - final Subject subject = new Subject(true, principals, Collections.EMPTY_SET, Collections.EMPTY_SET); - return subject; - } - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java deleted file mode 100644 index 75bc76c688..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipalTest.java +++ /dev/null @@ -1,123 +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.sasl; - -import junit.framework.TestCase; - -import javax.security.auth.Subject; -import java.security.Principal; - -/** - * Tests the UsernamePrincipal. - * - */ -public class UsernamePrincipalTest extends TestCase -{ - public void testEqualitySameObject() - { - final UsernamePrincipal principal = new UsernamePrincipal("string"); - assertTrue(principal.equals(principal)); - } - - public void testEqualitySameName() - { - final String string = "string"; - final UsernamePrincipal principal1 = new UsernamePrincipal(string); - final UsernamePrincipal principal2 = new UsernamePrincipal(string); - assertTrue(principal1.equals(principal2)); - } - - public void testEqualityEqualName() - { - final UsernamePrincipal principal1 = new UsernamePrincipal(new String("string")); - final UsernamePrincipal principal2 = new UsernamePrincipal(new String("string")); - assertTrue(principal1.equals(principal2)); - } - - public void testInequalityDifferentUserPrincipals() - { - UsernamePrincipal principal1 = new UsernamePrincipal("string1"); - UsernamePrincipal principal2 = new UsernamePrincipal("string2"); - assertFalse(principal1.equals(principal2)); - } - - public void testInequalityNonUserPrincipal() - { - UsernamePrincipal principal = new UsernamePrincipal("string"); - assertFalse(principal.equals(new String("string"))); - } - - public void testInequalityNull() - { - UsernamePrincipal principal = new UsernamePrincipal("string"); - assertFalse(principal.equals(null)); - } - - public void testGetUsernamePrincipalFromSubject() - { - final UsernamePrincipal expected = new UsernamePrincipal("name"); - final Principal other = new Principal() - { - public String getName() - { - return "otherprincipal"; - } - }; - - final Subject subject = new Subject(); - subject.getPrincipals().add(expected); - subject.getPrincipals().add(other); - - final UsernamePrincipal actual = UsernamePrincipal.getUsernamePrincipalFromSubject(subject); - assertSame(expected, actual); - } - - public void testUsernamePrincipalNotInSubject() - { - try - { - UsernamePrincipal.getUsernamePrincipalFromSubject(new Subject()); - fail("Exception not thrown"); - } - catch (IllegalArgumentException iae) - { - // PASS - } - } - - public void testTooManyUsernamePrincipalInSubject() - { - final Subject subject = new Subject(); - subject.getPrincipals().add(new UsernamePrincipal("name1")); - subject.getPrincipals().add(new UsernamePrincipal("name2")); - try - { - - UsernamePrincipal.getUsernamePrincipalFromSubject(subject); - fail("Exception not thrown"); - } - catch (IllegalArgumentException iae) - { - // PASS - } - } - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupDatabaseTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupDatabaseTest.java new file mode 100644 index 0000000000..b020c1655a --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupDatabaseTest.java @@ -0,0 +1,456 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.group; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; +import java.util.Set; + +import org.apache.qpid.server.security.group.FileGroupDatabase; + +import junit.framework.TestCase; + +public class FileGroupDatabaseTest extends TestCase +{ + private static final String USER1 = "user1"; + private static final String USER2 = "user2"; + private static final String USER3 = "user3"; + + private static final String MY_GROUP = "myGroup"; + private static final String MY_GROUP2 = "myGroup2"; + private static final String MY_GROUP1 = "myGroup1"; + + private FileGroupDatabase _groupDatabase = new FileGroupDatabase(); + private String _groupFile; + + public void testGetAllGroups() throws Exception + { + writeAndSetGroupFile("myGroup.users", USER1); + + Set groups = _groupDatabase.getAllGroups(); + assertEquals(1, groups.size()); + assertTrue(groups.contains(MY_GROUP)); + } + + public void testGetAllGroupsWhenGroupFileEmpty() throws Exception + { + _groupDatabase.setGroupFile(_groupFile); + + Set groups = _groupDatabase.getAllGroups(); + assertEquals(0, groups.size()); + } + + public void testMissingGroupFile() throws Exception + { + try + { + _groupDatabase.setGroupFile("/not/a/file"); + fail("Exception not thrown"); + } + catch (FileNotFoundException fnfe) + { + // PASS + } + } + + public void testInvalidFormat() throws Exception + { + writeGroupFile("name.notvalid", USER1); + + try + { + _groupDatabase.setGroupFile(_groupFile); + fail("Exception not thrown"); + } + catch (IllegalArgumentException gde) + { + // PASS + } + } + + public void testGetUsersInGroup() throws Exception + { + writeGroupFile("myGroup.users", "user1,user2,user3"); + + _groupDatabase.setGroupFile(_groupFile); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(3, users.size()); + } + + public void testDuplicateUsersInGroupAreConflated() throws Exception + { + writeAndSetGroupFile("myGroup.users", "user1,user1,user3,user1"); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(2, users.size()); + } + + public void testGetUsersWithEmptyGroup() throws Exception + { + writeAndSetGroupFile("myGroup.users", ""); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertTrue(users.isEmpty()); + } + + public void testGetUsersInNonExistentGroup() throws Exception + { + writeAndSetGroupFile("myGroup.users", "user1,user2,user3"); + + Set users = _groupDatabase.getUsersInGroup("groupDoesntExist"); + assertNotNull(users); + assertTrue(users.isEmpty()); + } + + public void testGetUsersInNullGroup() throws Exception + { + writeAndSetGroupFile(); + assertTrue(_groupDatabase.getUsersInGroup(null).isEmpty()); + } + + public void testGetGroupPrincipalsForUserWhenUserBelongsToOneGroup() throws Exception + { + writeAndSetGroupFile("myGroup.users", "user1,user2"); + Set groups = _groupDatabase.getGroupsForUser(USER1); + assertEquals(1, groups.size()); + assertTrue(groups.contains(MY_GROUP)); + } + + public void testGetGroupPrincipalsForUserWhenUserBelongsToTwoGroup() throws Exception + { + writeAndSetGroupFile("myGroup1.users", "user1,user2", + "myGroup2.users", "user1,user3"); + Set groups = _groupDatabase.getGroupsForUser(USER1); + assertEquals(2, groups.size()); + assertTrue(groups.contains(MY_GROUP1)); + assertTrue(groups.contains(MY_GROUP2)); + } + + public void testGetGroupPrincipalsForUserWhenUserAddedToGroup() throws Exception + { + writeAndSetGroupFile("myGroup1.users", "user1,user2", + "myGroup2.users", USER2); + Set groups = _groupDatabase.getGroupsForUser(USER1); + assertEquals(1, groups.size()); + assertTrue(groups.contains(MY_GROUP1)); + + _groupDatabase.addUserToGroup(USER1, MY_GROUP2); + + groups = _groupDatabase.getGroupsForUser(USER1); + assertEquals(2, groups.size()); + assertTrue(groups.contains(MY_GROUP1)); + assertTrue(groups.contains(MY_GROUP2)); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP2); + assertEquals(2, users.size()); + assertTrue(users.contains(USER1)); + assertTrue(users.contains(USER2)); + } + + public void testGetGroupPrincipalsForUserWhenUserRemovedFromGroup() throws Exception + { + writeAndSetGroupFile("myGroup1.users", "user1,user2", + "myGroup2.users", "user1,user2"); + Set groups = _groupDatabase.getGroupsForUser(USER1); + assertEquals(2, groups.size()); + assertTrue(groups.contains(MY_GROUP1)); + assertTrue(groups.contains(MY_GROUP2)); + + _groupDatabase.removeUserFromGroup(USER1, MY_GROUP2); + + groups = _groupDatabase.getGroupsForUser(USER1); + assertEquals(1, groups.size()); + assertTrue(groups.contains(MY_GROUP1)); + } + + public void testGetGroupPrincipalsForUserWhenUserAdddedToGroupTheyAreAlreadyIn() throws Exception + { + writeAndSetGroupFile("myGroup.users", USER1); + _groupDatabase.addUserToGroup(USER1, MY_GROUP); + + Set groups = _groupDatabase.getGroupsForUser(USER1); + + assertEquals(1, groups.size()); + assertTrue(groups.contains(MY_GROUP)); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertEquals(1, users.size()); + assertTrue(users.contains(USER1)); + } + + public void testGetGroupPrincipalsForUserWhenUserNotKnown() throws Exception + { + writeAndSetGroupFile("myGroup.users", "user1,user2"); + Set groups = _groupDatabase.getGroupsForUser(USER3); + assertEquals(0, groups.size()); + } + + public void testGetGroupPrincipalsForNullUser() throws Exception + { + writeAndSetGroupFile(); + assertTrue(_groupDatabase.getGroupsForUser(null).isEmpty()); + } + + public void testAddUserToExistingGroup() throws Exception + { + writeAndSetGroupFile("myGroup.users", "user1,user2"); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(2, users.size()); + + _groupDatabase.addUserToGroup(USER3, MY_GROUP); + + users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(3, users.size()); + } + + public void testAddUserToEmptyGroup() throws Exception + { + writeAndSetGroupFile("myGroup.users", ""); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(0, users.size()); + + _groupDatabase.addUserToGroup(USER3, MY_GROUP); + + users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(1, users.size()); + } + + public void testAddUserToNonExistentGroup() throws Exception + { + writeAndSetGroupFile(); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(0, users.size()); + + try + { + _groupDatabase.addUserToGroup(USER3, MY_GROUP); + fail("Expected exception not thrown"); + } + catch(IllegalArgumentException e) + { + // pass + } + + users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(0, users.size()); + } + + public void testRemoveUserFromExistingGroup() throws Exception + { + writeAndSetGroupFile("myGroup.users", "user1,user2"); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(2, users.size()); + + _groupDatabase.removeUserFromGroup(USER2, MY_GROUP); + + users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertNotNull(users); + assertEquals(1, users.size()); + } + + public void testRemoveUserFromNonexistentGroup() throws Exception + { + writeAndSetGroupFile(); + + try + { + _groupDatabase.removeUserFromGroup(USER1, MY_GROUP); + fail("Expected exception not thrown"); + } + catch(IllegalArgumentException e) + { + // pass + } + + assertTrue(_groupDatabase.getUsersInGroup(MY_GROUP).isEmpty()); + } + + public void testRemoveUserFromGroupTwice() throws Exception + { + writeAndSetGroupFile("myGroup.users", USER1); + assertTrue(_groupDatabase.getUsersInGroup(MY_GROUP).contains(USER1)); + + _groupDatabase.removeUserFromGroup(USER1, MY_GROUP); + assertTrue(_groupDatabase.getUsersInGroup(MY_GROUP).isEmpty()); + + _groupDatabase.removeUserFromGroup(USER1, MY_GROUP); + assertTrue(_groupDatabase.getUsersInGroup(MY_GROUP).isEmpty()); + } + + public void testAddUserPersistedToFile() throws Exception + { + writeAndSetGroupFile("myGroup.users", "user1,user2"); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertEquals(2, users.size()); + + _groupDatabase.addUserToGroup(USER3, MY_GROUP); + assertEquals(3, users.size()); + + FileGroupDatabase newGroupDatabase = new FileGroupDatabase(); + newGroupDatabase.setGroupFile(_groupFile); + + Set newUsers = newGroupDatabase.getUsersInGroup(MY_GROUP); + assertEquals(users.size(), newUsers.size()); + } + + public void testRemoveUserPersistedToFile() throws Exception + { + writeAndSetGroupFile("myGroup.users", "user1,user2"); + + Set users = _groupDatabase.getUsersInGroup(MY_GROUP); + assertEquals(2, users.size()); + + _groupDatabase.removeUserFromGroup(USER2, MY_GROUP); + assertEquals(1, users.size()); + + FileGroupDatabase newGroupDatabase = new FileGroupDatabase(); + newGroupDatabase.setGroupFile(_groupFile); + + Set newUsers = newGroupDatabase.getUsersInGroup(MY_GROUP); + assertEquals(users.size(), newUsers.size()); + } + + public void testCreateGroupPersistedToFile() throws Exception + { + writeAndSetGroupFile(); + + Set groups = _groupDatabase.getAllGroups(); + assertEquals(0, groups.size()); + + _groupDatabase.createGroup(MY_GROUP); + + groups = _groupDatabase.getAllGroups(); + assertEquals(1, groups.size()); + assertTrue(groups.contains(MY_GROUP)); + + FileGroupDatabase newGroupDatabase = new FileGroupDatabase(); + newGroupDatabase.setGroupFile(_groupFile); + + Set newGroups = newGroupDatabase.getAllGroups(); + assertEquals(1, newGroups.size()); + assertTrue(newGroups.contains(MY_GROUP)); + } + + public void testRemoveGroupPersistedToFile() throws Exception + { + writeAndSetGroupFile("myGroup1.users", "user1,user2", + "myGroup2.users", "user1,user2"); + + Set groups = _groupDatabase.getAllGroups(); + assertEquals(2, groups.size()); + + Set groupsForUser1 = _groupDatabase.getGroupsForUser(USER1); + assertEquals(2, groupsForUser1.size()); + + _groupDatabase.removeGroup(MY_GROUP1); + + groups = _groupDatabase.getAllGroups(); + assertEquals(1, groups.size()); + assertTrue(groups.contains(MY_GROUP2)); + + groupsForUser1 = _groupDatabase.getGroupsForUser(USER1); + assertEquals(1, groupsForUser1.size()); + + FileGroupDatabase newGroupDatabase = new FileGroupDatabase(); + newGroupDatabase.setGroupFile(_groupFile); + + Set newGroups = newGroupDatabase.getAllGroups(); + assertEquals(1, newGroups.size()); + assertTrue(newGroups.contains(MY_GROUP2)); + + Set newGroupsForUser1 = newGroupDatabase.getGroupsForUser(USER1); + assertEquals(1, newGroupsForUser1.size()); + assertTrue(newGroupsForUser1.contains(MY_GROUP2)); +} + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _groupFile = createEmptyTestGroupFile(); + } + + private void writeAndSetGroupFile(String... groupAndUsers) throws Exception + { + writeGroupFile(groupAndUsers); + _groupDatabase.setGroupFile(_groupFile); + } + + private void writeGroupFile(String... groupAndUsers) throws Exception + { + if (groupAndUsers.length % 2 != 0) + { + throw new IllegalArgumentException("Number of groupAndUsers must be even"); + } + + Properties props = new Properties(); + for (int i = 0 ; i < groupAndUsers.length; i=i+2) + { + String group = groupAndUsers[i]; + String users = groupAndUsers[i+1]; + props.put(group, users); + } + + props.store(new FileOutputStream(_groupFile), "test group file"); + } + + private String createEmptyTestGroupFile() throws IOException + { + File tmpGroupFile = File.createTempFile("groups", "grp"); + tmpGroupFile.deleteOnExit(); + + return tmpGroupFile.getAbsolutePath(); + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + + if (_groupFile != null) + { + File groupFile = new File(_groupFile); + if (groupFile.exists()) + { + groupFile.delete(); + } + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java new file mode 100644 index 0000000000..934c0082ea --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerFactoryTest.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.group; + +import java.util.HashMap; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.server.model.GroupProvider; +import org.apache.qpid.test.utils.TestFileUtils; + +public class FileGroupManagerFactoryTest extends TestCase +{ + + private FileGroupManagerFactory _factory = new FileGroupManagerFactory(); + private Map _configuration = new HashMap(); + private String _emptyButValidGroupFile = TestFileUtils.createTempFile(this).getAbsolutePath(); + + public void testInstanceCreated() throws Exception + { + _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.FILE_GROUP_MANAGER_TYPE); + _configuration.put(FileGroupManagerFactory.FILE, _emptyButValidGroupFile); + + GroupManager manager = _factory.createInstance(_configuration); + assertNotNull(manager); + assertTrue(manager instanceof FileGroupManager); + } + + public void testReturnsNullWhenNoConfig() throws Exception + { + GroupManager manager = _factory.createInstance(_configuration); + assertNull(manager); + } + + public void testReturnsNullWhenConfigNotForThisPlugin() throws Exception + { + _configuration.put(GroupProvider.TYPE, "other-group-manager"); + + GroupManager manager = _factory.createInstance(_configuration); + assertNull(manager); + } + + + public void testRejectsConfigThatIsMissingAttributeValue() throws Exception + { + _configuration.put(GroupProvider.TYPE, FileGroupManagerFactory.FILE_GROUP_MANAGER_TYPE); + _configuration.put(FileGroupManagerFactory.FILE, null); + + try + { + _factory.createInstance(_configuration); + fail("Exception not thrown"); + } + catch (RuntimeException re) + { + // PASS + } + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java new file mode 100644 index 0000000000..b83d25b206 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/group/FileGroupManagerTest.java @@ -0,0 +1,197 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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.group; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.security.Principal; +import java.util.Properties; +import java.util.Set; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.test.utils.QpidTestCase; + +public class FileGroupManagerTest extends QpidTestCase +{ + private static final String MYGROUP_USERS = "user1"; + private static final String MY_GROUP = "myGroup.users"; + private static final String MY_GROUP2 = "myGroup2.users"; + private File _tmpGroupFile; + private FileGroupManager _manager; + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + + if (_tmpGroupFile != null) + { + if (_tmpGroupFile.exists()) + { + _tmpGroupFile.delete(); + } + } + } + + public void testValidGroupFile() throws Exception + { + final String groupFileName = writeGroupFile(); + + _manager = new FileGroupManager(groupFileName); + assertNotNull(_manager); + } + + public void testNonExistentGroupFile() throws Exception + { + final String filePath = "/does.not.exist/"; + + try + { + _manager = new FileGroupManager(filePath); + fail("expected exception was not thrown"); + } + catch(IllegalConfigurationException ce) + { + assertNotNull(ce.getCause()); + assertTrue(ce.getCause() instanceof FileNotFoundException); + } + } + + public void testGetGroupPrincipalsForUser() throws Exception + { + final String groupFileName = writeGroupFile(); + _manager = new FileGroupManager(groupFileName); + + Set principals = _manager.getGroupPrincipalsForUser("user1"); + assertEquals(1, principals.size()); + assertTrue(principals.contains(new GroupPrincipal("myGroup"))); + } + + public void testGetUserPrincipalsForGroup() throws Exception + { + final String groupFileName = writeGroupFile(); + _manager = new FileGroupManager(groupFileName); + + Set principals = _manager.getUserPrincipalsForGroup("myGroup"); + assertEquals(1, principals.size()); + assertTrue(principals.contains(new UsernamePrincipal("user1"))); + } + + public void testGetGroupPrincipals() throws Exception + { + final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS, MY_GROUP2, MYGROUP_USERS); + _manager = new FileGroupManager(groupFileName); + + Set principals = _manager.getGroupPrincipals(); + assertEquals(2, principals.size()); + assertTrue(principals.contains(new GroupPrincipal("myGroup"))); + assertTrue(principals.contains(new GroupPrincipal("myGroup2"))); + } + + public void testCreateGroup() throws Exception + { + final String groupFileName = writeGroupFile(); + _manager = new FileGroupManager(groupFileName); + + Set principals = _manager.getGroupPrincipals(); + assertEquals(1, principals.size()); + + _manager.createGroup("myGroup2"); + + principals = _manager.getGroupPrincipals(); + assertEquals(2, principals.size()); + assertTrue(principals.contains(new GroupPrincipal("myGroup2"))); + } + + public void testRemoveGroup() throws Exception + { + final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS); + _manager = new FileGroupManager(groupFileName); + + Set principals = _manager.getGroupPrincipals(); + assertEquals(1, principals.size()); + + _manager.removeGroup("myGroup"); + + principals = _manager.getGroupPrincipals(); + assertEquals(0, principals.size()); + } + + public void testAddUserToGroup() throws Exception + { + final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS); + _manager = new FileGroupManager(groupFileName); + + Set principals = _manager.getUserPrincipalsForGroup("myGroup"); + assertEquals(1, principals.size()); + assertFalse(principals.contains(new UsernamePrincipal("user2"))); + + _manager.addUserToGroup("user2", "myGroup"); + + principals = _manager.getUserPrincipalsForGroup("myGroup"); + assertEquals(2, principals.size()); + assertTrue(principals.contains(new UsernamePrincipal("user2"))); + } + + public void testRemoveUserInGroup() throws Exception + { + final String groupFileName = writeGroupFile(MY_GROUP, MYGROUP_USERS); + _manager = new FileGroupManager(groupFileName); + + Set principals = _manager.getUserPrincipalsForGroup("myGroup"); + assertEquals(1, principals.size()); + assertTrue(principals.contains(new UsernamePrincipal("user1"))); + + _manager.removeUserFromGroup("user1", "myGroup"); + + principals = _manager.getUserPrincipalsForGroup("myGroup"); + assertEquals(0, principals.size()); + } + + private String writeGroupFile() throws Exception + { + return writeGroupFile(MY_GROUP, MYGROUP_USERS); + } + + private String writeGroupFile(String... groupAndUsers) throws Exception + { + if (groupAndUsers.length % 2 != 0) + { + throw new IllegalArgumentException("Number of groupAndUsers must be even"); + } + + _tmpGroupFile = File.createTempFile("groups", "grp"); + _tmpGroupFile.deleteOnExit(); + + Properties props = new Properties(); + for (int i = 0 ; i < groupAndUsers.length; i=i+2) + { + String group = groupAndUsers[i]; + String users = groupAndUsers[i+1]; + props.put(group, users); + } + + props.store(new FileOutputStream(_tmpGroupFile), "test group file"); + + return _tmpGroupFile.getCanonicalPath(); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/group/GroupPrincipalAccessorTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/group/GroupPrincipalAccessorTest.java new file mode 100644 index 0000000000..e58a1a01f8 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/group/GroupPrincipalAccessorTest.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.server.security.group; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.security.Principal; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import junit.framework.TestCase; + +import org.apache.qpid.server.model.GroupProvider; + +public class GroupPrincipalAccessorTest extends TestCase +{ + private static final String USERNAME = "username"; + + private GroupProvider _groupManager1 = mock(GroupProvider.class); + private GroupProvider _groupManager2 = mock(GroupProvider.class); + + private Principal _group1 = mock(Principal.class); + private Principal _group2 = mock(Principal.class); + + @Override + public void setUp() + { + when(_groupManager1.getGroupPrincipalsForUser(USERNAME)).thenReturn(Collections.singleton(_group1)); + when(_groupManager2.getGroupPrincipalsForUser(USERNAME)).thenReturn(Collections.singleton(_group2)); + } + + public void testGetGroupPrincipals() + { + getAndAssertGroupPrincipals(_group1, _group2); + } + + public void testGetGroupPrincipalsWhenAGroupManagerReturnsNull() + { + when(_groupManager1.getGroupPrincipalsForUser(USERNAME)).thenReturn(null); + + getAndAssertGroupPrincipals(_group2); + } + + public void testGetGroupPrincipalsWhenAGroupManagerReturnsEmptySet() + { + when(_groupManager2.getGroupPrincipalsForUser(USERNAME)).thenReturn(new HashSet()); + + getAndAssertGroupPrincipals(_group1); + } + + private void getAndAssertGroupPrincipals(Principal... expectedGroups) + { + GroupPrincipalAccessor groupPrincipalAccessor = new GroupPrincipalAccessor(Arrays.asList(_groupManager1, _groupManager2)); + + Set actualGroupPrincipals = groupPrincipalAccessor.getGroupPrincipals(USERNAME); + + Set expectedGroupPrincipals = new HashSet(Arrays.asList(expectedGroups)); + + assertEquals(expectedGroupPrincipals, actualGroupPrincipals); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/group/GroupPrincipalTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/group/GroupPrincipalTest.java new file mode 100644 index 0000000000..d285a0797a --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/group/GroupPrincipalTest.java @@ -0,0 +1,88 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.security.group; + +import org.apache.qpid.server.security.auth.UsernamePrincipal; + +import junit.framework.TestCase; + +public class GroupPrincipalTest extends TestCase +{ + public void testGetName() + { + final GroupPrincipal principal = new GroupPrincipal("group"); + assertEquals("group", principal.getName()); + } + + public void testAddRejected() + { + final GroupPrincipal principal = new GroupPrincipal("group"); + final UsernamePrincipal user = new UsernamePrincipal("name"); + + try + { + principal.addMember(user); + fail("Exception not thrown"); + } + catch (UnsupportedOperationException uso) + { + // PASS + } + } + + public void testEqualitySameName() + { + final String string = "string"; + final GroupPrincipal principal1 = new GroupPrincipal(string); + final GroupPrincipal principal2 = new GroupPrincipal(string); + assertTrue(principal1.equals(principal2)); + } + + public void testEqualityEqualName() + { + final GroupPrincipal principal1 = new GroupPrincipal(new String("string")); + final GroupPrincipal principal2 = new GroupPrincipal(new String("string")); + assertTrue(principal1.equals(principal2)); + } + + public void testInequalityDifferentGroupPrincipals() + { + GroupPrincipal principal1 = new GroupPrincipal("string1"); + GroupPrincipal principal2 = new GroupPrincipal("string2"); + assertFalse(principal1.equals(principal2)); + } + + public void testInequalityNonGroupPrincipal() + { + GroupPrincipal principal = new GroupPrincipal("string"); + assertFalse(principal.equals(new UsernamePrincipal("string"))); + } + + public void testInequalityNull() + { + GroupPrincipal principal = new GroupPrincipal("string"); + assertFalse(principal.equals(null)); + } + + + + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java b/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java deleted file mode 100644 index 23ee82eae6..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/signal/SignalHandlerTaskTest.java +++ /dev/null @@ -1,119 +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.signal; - -import org.apache.log4j.Logger; - -import org.apache.qpid.test.utils.QpidTestCase; - -import java.lang.management.ManagementFactory; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -public class SignalHandlerTaskTest extends QpidTestCase -{ - private static final Logger LOGGER = Logger.getLogger(SignalHandlerTaskTest.class); - private static final String SUN_MISC_SIGNAL_CLASS = "sun.misc.Signal"; - private static final String SUN_MISC_SIGNAL_HANDLER_CLASS = "sun.misc.SignalHandler"; - - protected void setUp() throws Exception - { - super.setUp(); - } - - public void testSignalHandlerTask() throws Exception - { - final boolean expectedResult = classifyExpectedRegistrationResult(); - final int pid = getPID(); - final CountDownLatch latch = new CountDownLatch(1); - - SignalHandlerTask hupReparseTask = new SignalHandlerTask() - { - public void handle() - { - latch.countDown(); - LOGGER.info("Signal handled, latch decremented"); - } - }; - - assertEquals("Unexpected result trying to register Signal handler", - expectedResult, hupReparseTask.register("HUP")); - LOGGER.info("Signal handler was registered"); - - assertEquals("unexpected count for the latch", 1, latch.getCount()); - - if(expectedResult) - { - //registration succeeded as expected, so now - //send SIGHUP and verify the handler was run - String cmd = "/bin/kill -SIGHUP " + pid; - - LOGGER.info("Sending SIGHUP"); - Runtime.getRuntime().exec(cmd); - - assertTrue("HUP Signal was not handled in the allowed timeframe", - latch.await(5, TimeUnit.SECONDS)); - } - } - - public void testGetPlatformDescription() throws Exception - { - assertNotNull(SignalHandlerTask.getPlatformDescription()); - } - - private boolean classifyExpectedRegistrationResult() - { - String os = System.getProperty("os.name"); - if(String.valueOf(os).toLowerCase().contains("windows")) - { - //Windows does not support SIGHUP so registration will fail - LOGGER.info("Running on windows, so we expect SIGHUP handler registration to fail"); - return false; - } - - //otherwise, if the signal handler classes are present we would expect - //registration to succeed - boolean classesPresent = true; - try - { - Class.forName(SUN_MISC_SIGNAL_CLASS); - Class.forName(SUN_MISC_SIGNAL_HANDLER_CLASS); - LOGGER.info("Signal handling classes were present so we expect SIGHUP handler registration to succeed"); - } - catch (ClassNotFoundException cnfe) - { - classesPresent = false; - } - - return classesPresent; - } - - private int getPID() - { - String processName = ManagementFactory.getRuntimeMXBean().getName(); - - int pid = Integer.parseInt(processName.substring(0,processName.indexOf('@'))); - LOGGER.info("PID was determined to be " + pid); - - return pid; - } - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java index cd8d91d835..f0ecfb6407 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java @@ -51,10 +51,6 @@ import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockStoredMessage; -import org.apache.qpid.server.store.ConfigurationRecoveryHandler; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreRecoveryHandler; -import org.apache.qpid.server.store.TransactionLogRecoveryHandler; import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BindingRecoveryHandler; import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecoveryHandler; import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler; @@ -76,7 +72,6 @@ public class DurableConfigurationStoreTest extends QpidTestCase private QueueRecoveryHandler _queueRecoveryHandler; private ExchangeRecoveryHandler _exchangeRecoveryHandler; private BindingRecoveryHandler _bindingRecoveryHandler; - private ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler _linkRecoveryHandler; private MessageStoreRecoveryHandler _messageStoreRecoveryHandler; private StoredMessageRecoveryHandler _storedMessageRecoveryHandler; private TransactionLogRecoveryHandler _logRecoveryHandler; @@ -116,7 +111,6 @@ public class DurableConfigurationStoreTest extends QpidTestCase when(_recoveryHandler.begin(isA(MessageStore.class))).thenReturn(_exchangeRecoveryHandler); when(_exchangeRecoveryHandler.completeExchangeRecovery()).thenReturn(_queueRecoveryHandler); when(_queueRecoveryHandler.completeQueueRecovery()).thenReturn(_bindingRecoveryHandler); - when(_bindingRecoveryHandler.completeBindingRecovery()).thenReturn(_linkRecoveryHandler); when(_logRecoveryHandler.begin(any(MessageStore.class))).thenReturn(_queueEntryRecoveryHandler); when(_queueEntryRecoveryHandler.completeQueueEntryRecovery()).thenReturn(_dtxRecordRecoveryHandler); when(_exchange.getNameShortString()).thenReturn(AMQShortString.valueOf(EXCHANGE_NAME)); @@ -161,7 +155,7 @@ public class DurableConfigurationStoreTest extends QpidTestCase public void testBindQueue() throws Exception { AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false); - Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), null, ROUTING_KEY, queue, + Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), ROUTING_KEY, queue, _exchange, FieldTable.convertToMap(_bindingArgs)); _store.bindQueue(binding); @@ -175,7 +169,7 @@ public class DurableConfigurationStoreTest extends QpidTestCase public void testUnbindQueue() throws Exception { AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false); - Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), null, ROUTING_KEY, queue, + Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), ROUTING_KEY, queue, _exchange, FieldTable.convertToMap(_bindingArgs)); _store.bindQueue(binding); diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreCreatorTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreCreatorTest.java new file mode 100644 index 0000000000..e74937dd1c --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreCreatorTest.java @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +import org.apache.qpid.server.store.derby.DerbyMessageStore; +import org.apache.qpid.test.utils.QpidTestCase; + +public class MessageStoreCreatorTest extends QpidTestCase +{ + private static final String[] STORE_TYPES = {MemoryMessageStore.TYPE, DerbyMessageStore.TYPE}; + + public void testMessageStoreCreator() + { + MessageStoreCreator messageStoreCreator = new MessageStoreCreator(); + for (String type : STORE_TYPES) + { + MessageStore store = messageStoreCreator.createMessageStore(type); + assertNotNull("Store of type " + type + " is not created", store); + } + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java index a1536565ad..ffd777243b 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.store; + import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.qpid.AMQException; @@ -35,11 +36,12 @@ import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.DirectExchange; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.exchange.ExchangeType; import org.apache.qpid.server.exchange.TopicExchange; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQPriorityQueue; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; @@ -48,11 +50,11 @@ import org.apache.qpid.server.queue.ConflationQueue; import org.apache.qpid.server.queue.IncomingMessage; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.queue.SimpleAMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.util.FileUtils; import java.io.File; @@ -66,7 +68,7 @@ import java.util.Map; * For persistent stores, it validates that Exchanges, Queues, Bindings and * Messages are persisted and recovered correctly. */ -public class MessageStoreTest extends InternalBrokerBaseCase +public class MessageStoreTest extends QpidTestCase { public static final int DEFAULT_PRIORTY_LEVEL = 5; public static final String SELECTOR_VALUE = "Test = 'MST'"; @@ -93,11 +95,15 @@ public class MessageStoreTest extends InternalBrokerBaseCase private AMQShortString queueOwner = new AMQShortString("MST"); - protected PropertiesConfiguration _config; + private PropertiesConfiguration _config; + + private VirtualHost _virtualHost; + private Broker _broker; public void setUp() throws Exception { super.setUp(); + BrokerTestHelper.setUp(); String storePath = System.getProperty("QPID_WORK") + File.separator + getName(); @@ -107,9 +113,38 @@ public class MessageStoreTest extends InternalBrokerBaseCase cleanup(new File(storePath)); + _broker = BrokerTestHelper.createBrokerMock(); + reloadVirtualHost(); } + @Override + public void tearDown() throws Exception + { + try + { + if (_virtualHost != null) + { + _virtualHost.close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + } + + public VirtualHost getVirtualHost() + { + return _virtualHost; + } + + public PropertiesConfiguration getConfig() + { + return _config; + } + protected void reloadVirtualHost() { VirtualHost original = getVirtualHost(); @@ -119,8 +154,6 @@ public class MessageStoreTest extends InternalBrokerBaseCase try { getVirtualHost().close(); - getVirtualHost().getApplicationRegistry(). - getVirtualHostRegistry().unregisterVirtualHost(getVirtualHost()); } catch (Exception e) { @@ -131,7 +164,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase try { - setVirtualHost(ApplicationRegistry.getInstance().createVirtualHost(new VirtualHostConfiguration(getClass().getName(), _config))); + _virtualHost = BrokerTestHelper.createVirtualHost(new VirtualHostConfiguration(getClass().getName(), _config, _broker)); } catch (Exception e) { @@ -628,7 +661,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase { //To change body of implemented methods use File | Settings | File Templates. } - }, 0L); + }); } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java index 4aa023a25c..7c6891da71 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java @@ -27,6 +27,7 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.test.utils.QpidTestCase; /** @@ -86,10 +87,12 @@ public class ReferenceCountingTest extends QpidTestCase AMQMessage message = new AMQMessage(storedMessage); - message.incrementReference(); + MessageReference ref = message.newReference(); assertEquals(1, _store.getMessageCount()); - message.decrementReference(); + + ref.release(); + assertEquals(0, _store.getMessageCount()); } @@ -142,13 +145,13 @@ public class ReferenceCountingTest extends QpidTestCase AMQMessage message = new AMQMessage(storedMessage); - message.incrementReference(); + MessageReference ref = message.newReference(); // we call routing complete to set up the handle // message.routingComplete(_store, _storeContext, new MessageHandleFactory()); assertEquals(1, _store.getMessageCount()); - message.incrementReference(); - message.decrementReference(); + MessageReference ref2 = message.newReference(); + ref.release(); assertEquals(1, _store.getMessageCount()); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java index 8c5d2684ff..a3552639d1 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java +++ b/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java @@ -294,17 +294,12 @@ public class MockSubscription implements Subscription private static class MockSessionModel implements AMQSessionModel { + private final UUID _id = UUID.randomUUID(); @Override - public int compareTo(AMQSessionModel o) - { - return 0; - } - - @Override - public UUID getQMFId() + public UUID getId() { - return null; + return _id; } @Override @@ -409,6 +404,12 @@ public class MockSubscription implements Subscription { return 0; } + + @Override + public int compareTo(AMQSessionModel o) + { + return getId().compareTo(o.getId()); + } } private static class MockConnectionModel implements AMQConnectionModel diff --git a/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java b/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java index 3272bd5447..d35a90e3c8 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java @@ -21,14 +21,75 @@ package org.apache.qpid.server.subscription; import org.apache.qpid.AMQException; +import org.apache.qpid.common.AMQPFilterTypes; +import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.SimpleAMQQueue; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TestableMemoryMessageStore; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; import java.util.List; -public class QueueBrowserUsesNoAckTest extends InternalBrokerBaseCase +public class QueueBrowserUsesNoAckTest extends QpidTestCase { + private AMQChannel _channel; + private SimpleAMQQueue _queue; + private MessageStore _messageStore; + private String _queueName; + + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _channel = BrokerTestHelper.createChannel(); + VirtualHost virtualHost = _channel.getVirtualHost(); + _queueName = getTestName(); + _queue = BrokerTestHelper.createQueue(_queueName, virtualHost); + _messageStore = virtualHost.getMessageStore(); + Exchange defaultExchange = virtualHost.getExchangeRegistry().getDefaultExchange(); + virtualHost.getBindingFactory().addBinding(_queueName, _queue, defaultExchange, null); + } + + @Override + public void tearDown() throws Exception + { + try + { + if (_channel != null) + { + _channel.getVirtualHost().close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + } + + private AMQChannel getChannel() + { + return _channel; + } + + private InternalTestProtocolSession getSession() + { + return (InternalTestProtocolSession)_channel.getProtocolSession(); + } + + private SimpleAMQQueue getQueue() + { + return _queue; + } public void testQueueBrowserUsesNoAck() throws AMQException { @@ -39,7 +100,7 @@ public class QueueBrowserUsesNoAckTest extends InternalBrokerBaseCase checkStoreContents(0); //Send required messsages to the queue - publishMessages(getSession(), getChannel(), sendMessageCount); + BrokerTestHelper.publishMessages(getChannel(), sendMessageCount, _queueName, ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString()); //Ensure they are stored checkStoreContents(sendMessageCount); @@ -74,4 +135,16 @@ public class QueueBrowserUsesNoAckTest extends InternalBrokerBaseCase .equals(Subscription.State.SUSPENDED)); } + private void checkStoreContents(int messageCount) + { + assertEquals("Message header count incorrect in the MetaDataMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getMessageCount()); + } + + private AMQShortString browse(AMQChannel channel, AMQQueue queue) throws AMQException + { + FieldTable filters = new FieldTable(); + filters.put(AMQPFilterTypes.NO_CONSUME.getValue(), true); + + return channel.subscribeToQueue(null, queue, true, filters, false, true); + } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java b/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java index 29f45bf7f4..89d434e95d 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java @@ -23,20 +23,55 @@ package org.apache.qpid.server.subscription; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.flow.WindowCreditManager; +import org.apache.qpid.server.logging.UnitTestMessageLogger; +import org.apache.qpid.server.logging.actors.GenericActor; +import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.protocol.ProtocolEngine_0_10; import org.apache.qpid.server.transport.ServerConnection; import org.apache.qpid.server.transport.ServerSession; import org.apache.qpid.server.transport.ServerSessionDelegate; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.transport.Binary; import org.apache.qpid.transport.MessageAcceptMode; import org.apache.qpid.transport.MessageAcquireMode; import org.apache.qpid.transport.MessageFlowMode; import org.apache.qpid.transport.TestNetworkConnection; -public class SubscriptionFactoryImplTest extends InternalBrokerBaseCase +public class SubscriptionFactoryImplTest extends QpidTestCase { + private AMQChannel _channel; + private AMQProtocolSession _session; + + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _channel = BrokerTestHelper.createChannel(); + _session = _channel.getProtocolSession(); + GenericActor.setDefaultMessageLogger(new UnitTestMessageLogger(false)); + } + + @Override + public void tearDown() throws Exception + { + try + { + if (_channel != null) + { + _channel.getVirtualHost().close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } + } + /** * Tests that while creating Subscriptions of various types, the * ID numbers assigned are allocated from a common sequence @@ -46,35 +81,34 @@ public class SubscriptionFactoryImplTest extends InternalBrokerBaseCase { //create a No-Ack subscription, get the first Subscription ID long previousId = 0; - Subscription noAckSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, getSession(), new AMQShortString("1"), false, null, false, getChannel().getCreditManager()); + Subscription noAckSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, _session, new AMQShortString("1"), false, null, false, _channel.getCreditManager()); previousId = noAckSub.getSubscriptionID(); //create an ack subscription, verify the next Subscription ID is used - Subscription ackSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, getSession(), new AMQShortString("1"), true, null, false, getChannel().getCreditManager()); + Subscription ackSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, _session, new AMQShortString("1"), true, null, false, _channel.getCreditManager()); assertEquals("Unexpected Subscription ID allocated", previousId + 1, ackSub.getSubscriptionID()); previousId = ackSub.getSubscriptionID(); //create a browser subscription FieldTable filters = new FieldTable(); filters.put(AMQPFilterTypes.NO_CONSUME.getValue(), true); - Subscription browerSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, getSession(), new AMQShortString("1"), true, null, false, getChannel().getCreditManager()); + Subscription browerSub = SubscriptionFactoryImpl.INSTANCE.createSubscription(1, _session, new AMQShortString("1"), true, null, false, _channel.getCreditManager()); assertEquals("Unexpected Subscription ID allocated", previousId + 1, browerSub.getSubscriptionID()); previousId = browerSub.getSubscriptionID(); //create an BasicGet NoAck subscription - Subscription getNoAckSub = SubscriptionFactoryImpl.INSTANCE.createBasicGetNoAckSubscription(getChannel(), getSession(), new AMQShortString("1"), null, false, - getChannel().getCreditManager(),getChannel().getClientDeliveryMethod(), getChannel().getRecordDeliveryMethod()); + Subscription getNoAckSub = SubscriptionFactoryImpl.INSTANCE.createBasicGetNoAckSubscription(_channel, _session, new AMQShortString("1"), null, false, + _channel.getCreditManager(),_channel.getClientDeliveryMethod(), _channel.getRecordDeliveryMethod()); assertEquals("Unexpected Subscription ID allocated", previousId + 1, getNoAckSub.getSubscriptionID()); previousId = getNoAckSub.getSubscriptionID(); //create a 0-10 subscription ServerConnection conn = new ServerConnection(1); - ProtocolEngine_0_10 engine = new ProtocolEngine_0_10(conn, new TestNetworkConnection(), getRegistry()); - conn.setVirtualHost(getVirtualHost()); - conn.setConnectionConfig(engine); + ProtocolEngine_0_10 engine = new ProtocolEngine_0_10(conn, new TestNetworkConnection()); + conn.setVirtualHost(_session.getVirtualHost()); ServerSessionDelegate sesDel = new ServerSessionDelegate(); Binary name = new Binary(new byte[]{new Byte("1")}); - ServerSession session = new ServerSession(conn, sesDel, name, 0, engine); + ServerSession session = new ServerSession(conn, sesDel, name, 0); Subscription sub_0_10 = SubscriptionFactoryImpl.INSTANCE.createSubscription(session, "1", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED, MessageFlowMode.WINDOW, new WindowCreditManager(), null, null); diff --git a/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java b/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java index d775b0f2f8..3389773ff8 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java @@ -1,5 +1,4 @@ /* - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -16,19 +15,17 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * */ package org.apache.qpid.server.transport; -import java.util.UUID; - -import org.apache.qpid.server.configuration.MockConnectionConfig; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.GenericActor; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.transport.Binary; -public class ServerSessionTest extends InternalBrokerBaseCase +public class ServerSessionTest extends QpidTestCase { private VirtualHost _virtualHost; @@ -37,31 +34,44 @@ public class ServerSessionTest extends InternalBrokerBaseCase public void setUp() throws Exception { super.setUp(); - _virtualHost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHosts().iterator().next(); + BrokerTestHelper.setUp(); + _virtualHost = BrokerTestHelper.createVirtualHost(getName()); + GenericActor.setDefaultMessageLogger(CurrentActor.get().getRootMessageLogger()); + } + + @Override + public void tearDown() throws Exception + { + try + { + if (_virtualHost != null) + { + _virtualHost.close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } } public void testCompareTo() throws Exception { ServerConnection connection = new ServerConnection(1); - connection.setConnectionConfig(createConnectionConfig()); + connection.setVirtualHost(_virtualHost); ServerSession session1 = new ServerSession(connection, new ServerSessionDelegate(), - new Binary(getName().getBytes()), 0 , connection.getConfig()); + new Binary(getName().getBytes()), 0); // create a session with the same name but on a different connection ServerConnection connection2 = new ServerConnection(2); - connection2.setConnectionConfig(createConnectionConfig()); + connection2.setVirtualHost(_virtualHost); ServerSession session2 = new ServerSession(connection2, new ServerSessionDelegate(), - new Binary(getName().getBytes()), 0 , connection2.getConfig()); + new Binary(getName().getBytes()), 0); assertFalse("Unexpected compare result", session1.compareTo(session2) == 0); assertEquals("Unexpected compare result", 0, session1.compareTo(session1)); } - private MockConnectionConfig createConnectionConfig() - { - return new MockConnectionConfig(UUID.randomUUID(), null, null, - false, 1, _virtualHost, "address", Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, - "authid", "remoteProcessName", new Integer(1967), new Integer(1970), _virtualHost.getConfigStore(), Boolean.FALSE); - } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java b/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java index 1aa91fa98a..5c1012d50b 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java @@ -82,7 +82,7 @@ public class AsyncAutoCommitTransactionTest extends QpidTestCase AsyncAutoCommitTransaction asyncAutoCommitTransaction = new AsyncAutoCommitTransaction(_messageStore, _futureRecorder); - asyncAutoCommitTransaction.enqueue(Collections.singletonList(_queue), _message, _postTransactionAction, System.currentTimeMillis()); + asyncAutoCommitTransaction.enqueue(Collections.singletonList(_queue), _message, _postTransactionAction); verify(_storeTransaction).enqueueMessage(_queue, _message); verify(_futureRecorder).recordFuture(_future, _postTransactionAction); diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java b/java/broker/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java index cd3fe3c473..06b8539eb1 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java @@ -137,7 +137,7 @@ public class AutoCommitTransactionTest extends QpidTestCase _message = createTestMessage(false); _queues = createTestBaseQueues(new boolean[] {false, false, false}); - _transaction.enqueue(_queues, _message, _action, 0L); + _transaction.enqueue(_queues, _message, _action); assertEquals("Enqueue of non-persistent message must not cause message to be enqueued", 0, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.NOT_STARTED, _storeTransaction.getState()); @@ -157,7 +157,7 @@ public class AutoCommitTransactionTest extends QpidTestCase _message = createTestMessage(true); _queues = createTestBaseQueues(new boolean[] {false, false, false}); - _transaction.enqueue(_queues, _message, _action, 0L); + _transaction.enqueue(_queues, _message, _action); assertEquals("Enqueue of persistent message to non-durable queues must not cause message to be enqueued", 0, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.NOT_STARTED, _storeTransaction.getState()); @@ -175,7 +175,7 @@ public class AutoCommitTransactionTest extends QpidTestCase _message = createTestMessage(true); _queues = createTestBaseQueues(new boolean[] {false, true, false, true}); - _transaction.enqueue(_queues, _message, _action, 0L); + _transaction.enqueue(_queues, _message, _action); assertEquals("Enqueue of persistent message to durable/non-durable queues must cause messages to be enqueued", 2, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.COMMITTED, _storeTransaction.getState()); @@ -198,7 +198,7 @@ public class AutoCommitTransactionTest extends QpidTestCase try { - _transaction.enqueue(_queues, _message, _action, 0L); + _transaction.enqueue(_queues, _message, _action); fail("Exception not thrown"); } catch (RuntimeException re) diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java b/java/broker/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java index 5992829f37..4904cbc6fb 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java @@ -140,7 +140,7 @@ public class LocalTransactionTest extends QpidTestCase _message = createTestMessage(false); _queues = createTestBaseQueues(new boolean[] {false, false, false}); - _transaction.enqueue(_queues, _message, _action1, 0L); + _transaction.enqueue(_queues, _message, _action1); assertEquals("Enqueue of non-persistent message must not cause message to be enqueued", 0, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.NOT_STARTED, _storeTransaction.getState()); @@ -156,7 +156,7 @@ public class LocalTransactionTest extends QpidTestCase _message = createTestMessage(true); _queues = createTestBaseQueues(new boolean[] {false, false, false}); - _transaction.enqueue(_queues, _message, _action1, 0L); + _transaction.enqueue(_queues, _message, _action1); assertEquals("Enqueue of persistent message to non-durable queues must not cause message to be enqueued", 0, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.NOT_STARTED, _storeTransaction.getState()); @@ -173,7 +173,7 @@ public class LocalTransactionTest extends QpidTestCase _message = createTestMessage(true); _queues = createTestBaseQueues(new boolean[] {false, true, false, true}); - _transaction.enqueue(_queues, _message, _action1, 0L); + _transaction.enqueue(_queues, _message, _action1); assertEquals("Enqueue of persistent message to durable/non-durable queues must cause messages to be enqueued", 2, _storeTransaction.getNumberOfEnqueuedMessages()); assertEquals("Unexpected transaction state", TransactionState.STARTED, _storeTransaction.getState()); @@ -196,7 +196,7 @@ public class LocalTransactionTest extends QpidTestCase try { - _transaction.enqueue(_queues, _message, _action1, 0L); + _transaction.enqueue(_queues, _message, _action1); fail("Exception not thrown"); } catch (RuntimeException re) @@ -217,7 +217,7 @@ public class LocalTransactionTest extends QpidTestCase { _message = createTestMessage(false); _queue = createTestAMQQueue(false); - + _transaction.dequeue(_queue, _message, _action1); assertEquals("Dequeue of non-persistent message must not cause message to be enqueued", 0, _storeTransaction.getNumberOfEnqueuedMessages()); @@ -465,7 +465,6 @@ public class LocalTransactionTest extends QpidTestCase */ public void testRollbackWorkWithAdditionalPostAction() throws Exception { - _message = createTestMessage(true); _queue = createTestAMQQueue(true); @@ -482,6 +481,122 @@ public class LocalTransactionTest extends QpidTestCase assertTrue("Rollback action2 must be fired", _action1.isRollbackActionFired()); } + public void testFirstEnqueueRecordsTransactionStartAndUpdateTime() throws Exception + { + assertEquals("Unexpected transaction start time before test", 0, _transaction.getTransactionStartTime()); + assertEquals("Unexpected transaction update time before test", 0, _transaction.getTransactionUpdateTime()); + + _message = createTestMessage(true); + _queue = createTestAMQQueue(true); + + long startTime = System.currentTimeMillis(); + _transaction.enqueue(_queue, _message, _action1); + + assertTrue("Transaction start time should have been recorded", _transaction.getTransactionStartTime() >= startTime); + assertEquals("Transaction update time should be the same as transaction start time", _transaction.getTransactionStartTime(), _transaction.getTransactionUpdateTime()); + } + + public void testSubsequentEnqueueAdvancesTransactionUpdateTimeOnly() throws Exception + { + assertEquals("Unexpected transaction start time before test", 0, _transaction.getTransactionStartTime()); + assertEquals("Unexpected transaction update time before test", 0, _transaction.getTransactionUpdateTime()); + + _message = createTestMessage(true); + _queue = createTestAMQQueue(true); + + _transaction.enqueue(_queue, _message, _action1); + + final long transactionStartTimeAfterFirstEnqueue = _transaction.getTransactionStartTime(); + final long transactionUpdateTimeAfterFirstEnqueue = _transaction.getTransactionUpdateTime(); + + Thread.sleep(1); + _transaction.enqueue(_queue, _message, _action2); + + final long transactionStartTimeAfterSecondEnqueue = _transaction.getTransactionStartTime(); + final long transactionUpdateTimeAfterSecondEnqueue = _transaction.getTransactionUpdateTime(); + + assertEquals("Transaction start time after second enqueue should be unchanged", transactionStartTimeAfterFirstEnqueue, transactionStartTimeAfterSecondEnqueue); + assertTrue("Transaction update time after second enqueue should be greater than first update time", transactionUpdateTimeAfterSecondEnqueue > transactionUpdateTimeAfterFirstEnqueue); + } + + public void testFirstDequeueRecordsTransactionStartAndUpdateTime() throws Exception + { + assertEquals("Unexpected transaction start time before test", 0, _transaction.getTransactionStartTime()); + assertEquals("Unexpected transaction update time before test", 0, _transaction.getTransactionUpdateTime()); + + _message = createTestMessage(true); + _queue = createTestAMQQueue(true); + + long startTime = System.currentTimeMillis(); + _transaction.dequeue(_queue, _message, _action1); + + assertTrue("Transaction start time should have been recorded", _transaction.getTransactionStartTime() >= startTime); + assertEquals("Transaction update time should be the same as transaction start time", _transaction.getTransactionStartTime(), _transaction.getTransactionUpdateTime()); + } + + public void testMixedEnqueuesAndDequeuesAdvancesTransactionUpdateTimeOnly() throws Exception + { + assertEquals("Unexpected transaction start time before test", 0, _transaction.getTransactionStartTime()); + assertEquals("Unexpected transaction update time before test", 0, _transaction.getTransactionUpdateTime()); + + _message = createTestMessage(true); + _queue = createTestAMQQueue(true); + + _transaction.enqueue(_queue, _message, _action1); + + final long transactionStartTimeAfterFirstEnqueue = _transaction.getTransactionStartTime(); + final long transactionUpdateTimeAfterFirstEnqueue = _transaction.getTransactionUpdateTime(); + + Thread.sleep(1); + _transaction.dequeue(_queue, _message, _action2); + + final long transactionStartTimeAfterFirstDequeue = _transaction.getTransactionStartTime(); + final long transactionUpdateTimeAfterFirstDequeue = _transaction.getTransactionUpdateTime(); + + assertEquals("Transaction start time after first dequeue should be unchanged", transactionStartTimeAfterFirstEnqueue, transactionStartTimeAfterFirstDequeue); + assertTrue("Transaction update time after first dequeue should be greater than first update time", transactionUpdateTimeAfterFirstDequeue > transactionUpdateTimeAfterFirstEnqueue); + } + + public void testCommitResetsTransactionStartAndUpdateTime() throws Exception + { + assertEquals("Unexpected transaction start time before test", 0, _transaction.getTransactionStartTime()); + assertEquals("Unexpected transaction update time before test", 0, _transaction.getTransactionUpdateTime()); + + _message = createTestMessage(true); + _queue = createTestAMQQueue(true); + + long startTime = System.currentTimeMillis(); + _transaction.enqueue(_queue, _message, _action1); + + assertTrue(_transaction.getTransactionStartTime() >= startTime); + assertTrue(_transaction.getTransactionUpdateTime() >= startTime); + + _transaction.commit(); + + assertEquals("Transaction start time should be reset after commit", 0, _transaction.getTransactionStartTime()); + assertEquals("Transaction update time should be reset after commit", 0, _transaction.getTransactionUpdateTime()); + } + + public void testRollbackResetsTransactionStartAndUpdateTime() throws Exception + { + assertEquals("Unexpected transaction start time before test", 0, _transaction.getTransactionStartTime()); + assertEquals("Unexpected transaction update time before test", 0, _transaction.getTransactionUpdateTime()); + + _message = createTestMessage(true); + _queue = createTestAMQQueue(true); + + long startTime = System.currentTimeMillis(); + _transaction.enqueue(_queue, _message, _action1); + + assertTrue(_transaction.getTransactionStartTime() >= startTime); + assertTrue(_transaction.getTransactionUpdateTime() >= startTime); + + _transaction.rollback(); + + assertEquals("Transaction start time should be reset after rollback", 0, _transaction.getTransactionStartTime()); + assertEquals("Transaction update time should be reset after rollback", 0, _transaction.getTransactionUpdateTime()); + } + private Collection createTestQueueEntries(boolean[] queueDurableFlags, boolean[] messagePersistentFlags) { Collection queueEntries = new ArrayList(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java b/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java index f3b6cab626..aa5b555b3b 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/MockServerMessage.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.txn; import org.apache.commons.lang.NotImplementedException; -import org.apache.qpid.server.configuration.SessionConfig; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; @@ -68,11 +67,6 @@ class MockServerMessage implements ServerMessage throw new NotImplementedException(); } - public SessionConfig getSessionConfig() - { - throw new NotImplementedException(); - } - public String getRoutingKey() { throw new NotImplementedException(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java new file mode 100644 index 0000000000..3be8927224 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java @@ -0,0 +1,209 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.util; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.SocketAddress; +import java.util.Collections; +import java.util.UUID; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore; +import org.apache.qpid.server.exchange.DefaultExchangeFactory; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.SystemOutMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.GenericActor; +import org.apache.qpid.server.logging.actors.TestLogActor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.InternalTestProtocolSession; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.SimpleAMQQueue; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.store.TestableMemoryMessageStore; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; + +public class BrokerTestHelper +{ + + protected static final String BROKER_STORE_CLASS_NAME_KEY = "brokerstore.class.name"; + protected static final String JSON_BROKER_STORE_CLASS_NAME = JsonConfigurationEntryStore.class.getName(); + + public static Broker createBrokerMock() + { + SubjectCreator subjectCreator = mock(SubjectCreator.class); + when(subjectCreator.getMechanisms()).thenReturn(""); + Broker broker = mock(Broker.class); + when(broker.getAttribute(Broker.SESSION_COUNT_LIMIT)).thenReturn(1); + when(broker.getAttribute(Broker.HOUSEKEEPING_CHECK_PERIOD)).thenReturn(10000l); + when(broker.getId()).thenReturn(UUID.randomUUID()); + when(broker.getSubjectCreator(any(SocketAddress.class))).thenReturn(subjectCreator); + RootMessageLogger rootMessageLogger = CurrentActor.get().getRootMessageLogger(); + when(broker.getRootMessageLogger()).thenReturn(rootMessageLogger); + when(broker.getVirtualHostRegistry()).thenReturn(new VirtualHostRegistry()); + when(broker.getSecurityManager()).thenReturn(new SecurityManager(null)); + GenericActor.setDefaultMessageLogger(rootMessageLogger); + return broker; + } + + public static void setUp() + { + CurrentActor.set(new TestLogActor(new SystemOutMessageLogger())); + } + + public static void tearDown() + { + CurrentActor.remove(); + } + + public static VirtualHost createVirtualHost(VirtualHostConfiguration virtualHostConfiguration, VirtualHostRegistry virtualHostRegistry) + throws Exception + { + StatisticsGatherer statisticsGatherer = mock(StatisticsGatherer.class); + VirtualHost host = new VirtualHostImpl(virtualHostRegistry, statisticsGatherer, new SecurityManager(null), virtualHostConfiguration); + virtualHostRegistry.registerVirtualHost(host); + return host; + } + + public static VirtualHost createVirtualHost(VirtualHostConfiguration virtualHostConfiguration) throws Exception + { + return new VirtualHostImpl(null, mock(StatisticsGatherer.class), new SecurityManager(null), virtualHostConfiguration); + } + + public static VirtualHost createVirtualHost(String name, VirtualHostRegistry virtualHostRegistry) throws Exception + { + VirtualHostConfiguration vhostConfig = createVirtualHostConfiguration(name); + return createVirtualHost(vhostConfig, virtualHostRegistry); + } + + public static VirtualHost createVirtualHost(String name) throws Exception + { + VirtualHostConfiguration configuration = createVirtualHostConfiguration(name); + return createVirtualHost(configuration); + } + + private static VirtualHostConfiguration createVirtualHostConfiguration(String name) throws ConfigurationException + { + VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration(name, new PropertiesConfiguration(), createBrokerMock()); + vhostConfig.setMessageStoreClass(TestableMemoryMessageStore.class.getName()); + return vhostConfig; + } + + public static AMQChannel createChannel(int channelId, AMQProtocolSession session) throws AMQException + { + AMQChannel channel = new AMQChannel(session, channelId, session.getVirtualHost().getMessageStore()); + session.addChannel(channel); + return channel; + } + + public static AMQChannel createChannel(int channelId) throws Exception + { + InternalTestProtocolSession session = createSession(); + return createChannel(channelId, session); + } + + public static AMQChannel createChannel() throws Exception + { + return createChannel(1); + } + + public static InternalTestProtocolSession createSession() throws Exception + { + return createSession("test"); + } + + public static InternalTestProtocolSession createSession(String hostName) throws Exception + { + VirtualHost virtualHost = createVirtualHost(hostName); + return new InternalTestProtocolSession(virtualHost, createBrokerMock()); + } + + public static Exchange createExchange(String hostName) throws Exception + { + SecurityManager securityManager = new SecurityManager(null); + VirtualHost virtualHost = mock(VirtualHost.class); + when(virtualHost.getName()).thenReturn(hostName); + when(virtualHost.getSecurityManager()).thenReturn(securityManager); + DefaultExchangeFactory factory = new DefaultExchangeFactory(virtualHost); + return factory.createExchange("amp.direct", "direct", false, false); + } + + public static void publishMessages(AMQChannel channel, int numberOfMessages, String queueName, String exchangeName) throws AMQException + { + AMQShortString rouningKey = new AMQShortString(queueName); + AMQShortString exchangeNameAsShortString = new AMQShortString(exchangeName); + MessagePublishInfo info = mock(MessagePublishInfo.class); + when(info.getExchange()).thenReturn(exchangeNameAsShortString); + when(info.getRoutingKey()).thenReturn(rouningKey); + + Exchange exchange = channel.getVirtualHost().getExchangeRegistry().getExchange(exchangeName); + for (int count = 0; count < numberOfMessages; count++) + { + channel.setPublishFrame(info, exchange); + + // Set the body size + ContentHeaderBody _headerBody = new ContentHeaderBody(); + _headerBody.setBodySize(0); + + // Set Minimum properties + BasicContentHeaderProperties properties = new BasicContentHeaderProperties(); + + properties.setExpiration(0L); + properties.setTimestamp(System.currentTimeMillis()); + + // Make Message Persistent + properties.setDeliveryMode((byte) 2); + + _headerBody.setProperties(properties); + + channel.publishContentHeader(_headerBody); + } + channel.sync(); + } + + public static SimpleAMQQueue createQueue(String queueName, VirtualHost virtualHost) throws AMQException + { + SimpleAMQQueue queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, null, + false, false, virtualHost, Collections.emptyMap()); + virtualHost.getQueueRegistry().registerQueue(queue); + return queue; + } + + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java b/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java deleted file mode 100644 index d7a9078412..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java +++ /dev/null @@ -1,372 +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.util; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.AMQException; -import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.logging.SystemOutMessageLogger; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.TestLogActor; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.test.utils.QpidTestCase; - - -public class InternalBrokerBaseCase extends QpidTestCase -{ - private IApplicationRegistry _registry; - private MessageStore _messageStore; - private AMQChannel _channel; - private InternalTestProtocolSession _session; - private VirtualHost _virtualHost; - private AMQQueue _queue; - private AMQShortString QUEUE_NAME; - private ServerConfiguration _configuration; - private XMLConfiguration _configXml = new XMLConfiguration(); - private boolean _started = false; - - public void setUp() throws Exception - { - super.setUp(); - - _configXml.addProperty("virtualhosts.virtualhost.name", "test"); - _configXml.addProperty("virtualhosts.virtualhost.test.store.class", TestableMemoryMessageStore.class.getName()); - - _configXml.addProperty("virtualhosts.virtualhost(-1).name", getName()); - _configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName()); - - createBroker(); - } - - protected void createBroker() throws Exception - { - _started = true; - CurrentActor.set(new TestLogActor(new SystemOutMessageLogger())); - - _configuration = new ServerConfiguration(_configXml); - - configure(); - - _registry = createApplicationRegistry(); - ApplicationRegistry.initialise(_registry); - _registry.getVirtualHostRegistry().setDefaultVirtualHostName(getName()); - _virtualHost = _registry.getVirtualHostRegistry().getVirtualHost(getName()); - - QUEUE_NAME = new AMQShortString("test"); - // Create a queue on the test Vhost.. this will aid in diagnosing duff tests - // as the ExpiredMessage Task will log with the test Name. - _queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), QUEUE_NAME.asString(), false, "testowner", - false, false, _virtualHost, null); - - Exchange defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange(); - _virtualHost.getBindingFactory().addBinding(QUEUE_NAME.toString(), _queue, defaultExchange, null); - - _virtualHost = _registry.getVirtualHostRegistry().getVirtualHost("test"); - _messageStore = _virtualHost.getMessageStore(); - - _queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), getName(), false, "testowner", - false, false, _virtualHost, null); - - _virtualHost.getQueueRegistry().registerQueue(_queue); - - defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange(); - - _virtualHost.getBindingFactory().addBinding(getName(), _queue, defaultExchange, null); - - _session = new InternalTestProtocolSession(_virtualHost); - CurrentActor.set(_session.getLogActor()); - - _channel = new AMQChannel(_session, 1, _messageStore); - - _session.addChannel(_channel); - } - - protected IApplicationRegistry createApplicationRegistry() throws ConfigurationException - { - return new TestApplicationRegistry(_configuration); - } - - protected void configure() - { - // Allow other tests to override configuration - } - - protected void stopBroker() - { - try - { - //Remove the ProtocolSession Actor added during createBroker - CurrentActor.remove(); - } - finally - { - ApplicationRegistry.remove(); - _started = false; - } - } - - - public void tearDown() throws Exception - { - try - { - if (_started) - { - stopBroker(); - } - } - finally - { - super.tearDown(); - // Purge Any erroneously added actors - CurrentActor.removeAll(); - } - } - - protected void checkStoreContents(int messageCount) - { - assertEquals("Message header count incorrect in the MetaDataMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getMessageCount()); - - //The above publish message is sufficiently small not to fit in the header so no Body is required. - //assertEquals("Message body count incorrect in the ContentBodyMap", messageCount, ((TestableMemoryMessageStore) _messageStore).getContentBodyMap().size()); - } - - protected AMQShortString subscribe(InternalTestProtocolSession session, AMQChannel channel, AMQQueue queue) - { - try - { - return channel.subscribeToQueue(null, queue, true, null, false, true); - } - catch (AMQException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - - //Keep the compiler happy - return null; - } - - protected AMQShortString browse(AMQChannel channel, AMQQueue queue) - { - try - { - FieldTable filters = new FieldTable(); - filters.put(AMQPFilterTypes.NO_CONSUME.getValue(), true); - - return channel.subscribeToQueue(null, queue, true, filters, false, true); - } - catch (AMQException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - - //Keep the compiler happy - return null; - } - - public void publishMessages(InternalTestProtocolSession session, AMQChannel channel, int messages) throws AMQException - { - MessagePublishInfo info = new MessagePublishInfo() - { - public AMQShortString getExchange() - { - return ExchangeDefaults.DEFAULT_EXCHANGE_NAME; - } - - public void setExchange(AMQShortString exchange) - { - - } - - public boolean isImmediate() - { - return false; - } - - public boolean isMandatory() - { - return false; - } - - public AMQShortString getRoutingKey() - { - return new AMQShortString(getName()); - } - }; - - for (int count = 0; count < messages; count++) - { - channel.setPublishFrame(info, _virtualHost.getExchangeRegistry().getExchange(info.getExchange())); - - //Set the body size - ContentHeaderBody _headerBody = new ContentHeaderBody(); - _headerBody.setBodySize(0); - - //Set Minimum properties - BasicContentHeaderProperties properties = new BasicContentHeaderProperties(); - - properties.setExpiration(0L); - properties.setTimestamp(System.currentTimeMillis()); - - //Make Message Persistent - properties.setDeliveryMode((byte) 2); - - _headerBody.setProperties(properties); - - channel.publishContentHeader(_headerBody); - } - channel.sync(); - } - - public void acknowledge(AMQChannel channel, long deliveryTag) - { - try - { - channel.acknowledgeMessage(deliveryTag, false); - } - catch (AMQException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - } - - public IApplicationRegistry getRegistry() - { - return _registry; - } - - public void setRegistry(IApplicationRegistry registry) - { - _registry = registry; - } - - public MessageStore getMessageStore() - { - return _messageStore; - } - - public void setMessageStore(MessageStore messageStore) - { - _messageStore = messageStore; - } - - public AMQChannel getChannel() - { - return _channel; - } - - public void setChannel(AMQChannel channel) - { - _channel = channel; - } - - public InternalTestProtocolSession getSession() - { - return _session; - } - - public void setSession(InternalTestProtocolSession session) - { - _session = session; - } - - public VirtualHost getVirtualHost() - { - return _virtualHost; - } - - public void setVirtualHost(VirtualHost virtualHost) - { - _virtualHost = virtualHost; - } - - public AMQQueue getQueue() - { - return _queue; - } - - public void setQueue(AMQQueue queue) - { - _queue = queue; - } - - public AMQShortString getQUEUE_NAME() - { - return QUEUE_NAME; - } - - public void setQUEUE_NAME(AMQShortString QUEUE_NAME) - { - this.QUEUE_NAME = QUEUE_NAME; - } - - public ServerConfiguration getConfiguration() - { - return _configuration; - } - - public void setConfiguration(ServerConfiguration configuration) - { - _configuration = configuration; - } - - public XMLConfiguration getConfigXml() - { - return _configXml; - } - - public void setConfigXml(XMLConfiguration configXml) - { - _configXml = configXml; - } - - public boolean isStarted() - { - return _started; - } - - public void setStarted(boolean started) - { - _started = started; - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java b/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java deleted file mode 100644 index a64ab620ab..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java +++ /dev/null @@ -1,121 +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.util; - -import java.net.SocketAddress; -import java.util.Collections; -import java.util.Map; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.logging.NullRootMessageLogger; -import org.apache.qpid.server.logging.actors.BrokerActor; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.GenericActor; -import org.apache.qpid.server.plugins.PluginManager; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabase; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry; -import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; - -import java.util.Properties; - -public class TestApplicationRegistry extends ApplicationRegistry -{ - - public TestApplicationRegistry(ServerConfiguration config) throws ConfigurationException - { - super(config); - } - - @Override - public void initialise() throws Exception - { - CurrentActor.setDefault(new BrokerActor(new NullRootMessageLogger())); - GenericActor.setDefaultMessageLogger(new NullRootMessageLogger()); - super.initialise(); - } - - @Override - protected IAuthenticationManagerRegistry createAuthenticationManagerRegistry( - ServerConfiguration _configuration, PluginManager _pluginManager) - throws ConfigurationException - { - final Properties users = new Properties(); - users.put("guest","guest"); - users.put("admin","admin"); - - final PropertiesPrincipalDatabase ppd = new PropertiesPrincipalDatabase(users); - - final AuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager() - { - - /** - * @see org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager#configure(org.apache.qpid.server.configuration.plugins.ConfigurationPlugin) - */ - @Override - public void configure(ConfigurationPlugin config) throws ConfigurationException - { - // We don't pass configuration to this test instance. - } - - @Override - public void initialise() - { - setPrincipalDatabase(ppd); - - super.initialise(); - } - }; - pdam.initialise(); - - return new IAuthenticationManagerRegistry() - { - @Override - public void close() - { - pdam.close(); - } - - @Override - public AuthenticationManager getAuthenticationManager( - SocketAddress address) - { - return pdam; - } - - @Override - public Map getAvailableAuthenticationManagers() - { - return Collections.singletonMap(pdam.getClass().getName(), pdam); - } - - @Override - public void addRegistryChangeListener(RegistryChangeListener listener) - { - } - }; - } -} - - diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java index 290c465785..1d99d99820 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java +++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java @@ -22,26 +22,18 @@ package org.apache.qpid.server.virtualhost; import java.util.concurrent.ScheduledFuture; import org.apache.qpid.server.binding.BindingFactory; -import org.apache.qpid.server.configuration.BrokerConfig; -import org.apache.qpid.server.configuration.ConfigStore; -import org.apache.qpid.server.configuration.ConfiguredObject; -import org.apache.qpid.server.configuration.VirtualHostConfig; -import org.apache.qpid.server.configuration.VirtualHostConfigType; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.protocol.v1_0.LinkRegistry; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.txn.DtxRegistry; -import java.util.Map; import java.util.UUID; public class MockVirtualHost implements VirtualHost @@ -58,19 +50,8 @@ public class MockVirtualHost implements VirtualHost } - public void createBrokerConnection(String transport, String host, int port, - String vhost, boolean durable, String authMechanism, - String username, String password) - { - - } - - public BrokerLink createBrokerConnection(final UUID id, final long createTime, final Map arguments) - { - return null; - } - - public IApplicationRegistry getApplicationRegistry() + @Override + public VirtualHostRegistry getVirtualHostRegistry() { return null; } @@ -85,16 +66,6 @@ public class MockVirtualHost implements VirtualHost return null; } - public UUID getBrokerId() - { - return null; - } - - public ConfigStore getConfigStore() - { - return null; - } - public DtxRegistry getDtxRegistry() { return null; @@ -160,12 +131,6 @@ public class MockVirtualHost implements VirtualHost return null; } - - public void removeBrokerConnection(BrokerLink brokerLink) - { - - } - public LinkRegistry getLinkRegistry(String remoteContainerId) { return null; @@ -186,25 +151,6 @@ public class MockVirtualHost implements VirtualHost } - public BrokerConfig getBroker() - { - return null; - } - - public String getFederationTag() - { - return null; - } - - public void setBroker(BrokerConfig brokerConfig) - { - - } - - public VirtualHostConfigType getConfigType() - { - return null; - } public long getCreateTime() { @@ -216,17 +162,6 @@ public class MockVirtualHost implements VirtualHost return null; } - @Override - public UUID getQMFId() - { - return null; - } - - public ConfiguredObject getParent() - { - return null; - } - public boolean isDurable() { return false; diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java index b8ba76e43d..559a7f8aaf 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java @@ -20,15 +20,21 @@ */ package org.apache.qpid.server.virtualhost; +import static org.mockito.Mockito.mock; + +import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; +import org.apache.commons.configuration.PropertiesConfiguration; + +import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.store.MemoryMessageStore; -import org.apache.qpid.server.util.TestApplicationRegistry; +import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.test.utils.QpidTestCase; import java.io.BufferedWriter; @@ -38,15 +44,31 @@ import java.io.IOException; public class VirtualHostImplTest extends QpidTestCase { - private ServerConfiguration _configuration; - private ApplicationRegistry _registry; + private VirtualHostRegistry _virtualHostRegistry; + + @Override + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + } @Override public void tearDown() throws Exception { - super.tearDown(); + try + { + if (_virtualHostRegistry != null) + { + _virtualHostRegistry.close(); + } + } + finally + { + BrokerTestHelper.tearDown(); + super.tearDown(); + } - ApplicationRegistry.remove(); } /** @@ -74,17 +96,23 @@ public class VirtualHostImplTest extends QpidTestCase */ public void testSpecifyingCustomBindingForDefaultExchangeThrowsException() throws Exception { - File config = writeConfigFile(getName(), getName(), null, false, new String[]{"custom-binding"}); + final String queueName = getName(); + final String customBinding = "custom-binding"; + File config = writeConfigFile(queueName, queueName, null, false, new String[]{customBinding}); try { - createVirtualHost(getName(), config); + createVirtualHost(queueName, config); fail("virtualhost creation should have failed due to illegal configuration"); } catch (RuntimeException e) { + assertNotNull(e.getCause()); + assertEquals(ConfigurationException.class, e.getCause().getClass()); - //expected + + Throwable configException = e.getCause(); + assertEquals("Illegal attempt to bind queue '" + queueName + "' to the default exchange with a key other than the queue name: " + customBinding, configException.getMessage()); } } @@ -96,6 +124,14 @@ public class VirtualHostImplTest extends QpidTestCase assertEquals(State.ACTIVE, vhost.getState()); } + public void testVirtualHostHavingStoreSetAsTypeBecomesActive() throws Exception + { + String virtualHostName = getName(); + VirtualHost host = createVirtualHostUsingStoreType(virtualHostName); + assertNotNull(host); + assertEquals(State.ACTIVE, host.getState()); + } + public void testVirtualHostBecomesStoppedOnClose() throws Exception { File config = writeConfigFile(getName(), getName(), getName() +".direct", false, new String[0]); @@ -107,22 +143,39 @@ public class VirtualHostImplTest extends QpidTestCase assertEquals(0, vhost.getHouseKeepingActiveCount()); } + public void testVirtualHostHavingStoreSetAsTypeBecomesStoppedOnClose() throws Exception + { + String virtualHostName = getName(); + VirtualHost host = createVirtualHostUsingStoreType(virtualHostName); + assertNotNull(host); + assertEquals(State.ACTIVE, host.getState()); + host.close(); + assertEquals(State.STOPPED, host.getState()); + assertEquals(0, host.getHouseKeepingActiveCount()); + } + /** * Tests that specifying an unknown exchange to bind the queue to results in failure to create the vhost */ public void testSpecifyingUnknownExchangeThrowsException() throws Exception { - File config = writeConfigFile(getName(), getName(), "made-up-exchange", true, new String[0]); + final String queueName = getName(); + final String exchangeName = "made-up-exchange"; + File config = writeConfigFile(queueName, queueName, exchangeName, true, new String[0]); try { - createVirtualHost(getName(), config); + createVirtualHost(queueName, config); fail("virtualhost creation should have failed due to illegal configuration"); } catch (RuntimeException e) { + assertNotNull(e.getCause()); + assertEquals(ConfigurationException.class, e.getCause().getClass()); - //expected + + Throwable configException = e.getCause(); + assertEquals("Attempt to bind queue '" + queueName + "' to unknown exchange:" + exchangeName, configException.getMessage()); } } @@ -154,12 +207,14 @@ public class VirtualHostImplTest extends QpidTestCase private VirtualHost createVirtualHost(String vhostName, File config) throws Exception { - _configuration = new ServerConfiguration(new XMLConfiguration(config)); + Broker broker = BrokerTestHelper.createBrokerMock(); + _virtualHostRegistry = broker.getVirtualHostRegistry(); - _registry = new TestApplicationRegistry(_configuration); - ApplicationRegistry.initialise(_registry); + VirtualHostConfiguration configuration = new VirtualHostConfiguration(vhostName, config, broker); + VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(null), configuration); + _virtualHostRegistry.registerVirtualHost(host); - return _registry.getVirtualHostRegistry().getVirtualHost(vhostName); + return host; } /** @@ -184,7 +239,6 @@ public class VirtualHostImplTest extends QpidTestCase BufferedWriter writer = new BufferedWriter(fstream); //extra outer tag to please Commons Configuration - writer.write(""); writer.write(""); writer.write(" " + vhostName + ""); @@ -222,8 +276,6 @@ public class VirtualHostImplTest extends QpidTestCase writer.write(" "); writer.write(""); - writer.write(""); - writer.flush(); writer.close(); } @@ -234,4 +286,17 @@ public class VirtualHostImplTest extends QpidTestCase return tmpFile; } + + private VirtualHost createVirtualHostUsingStoreType(String virtualHostName) throws ConfigurationException, Exception + { + Broker broker = BrokerTestHelper.createBrokerMock(); + _virtualHostRegistry = broker.getVirtualHostRegistry(); + + Configuration config = new PropertiesConfiguration(); + config.setProperty("store.type", MemoryMessageStore.TYPE); + VirtualHostConfiguration configuration = new VirtualHostConfiguration(virtualHostName, config, broker); + VirtualHost host = new VirtualHostImpl(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(null), configuration); + _virtualHostRegistry.registerVirtualHost(host); + return host; + } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionConfigurationTest.java deleted file mode 100644 index e2375c579b..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionConfigurationTest.java +++ /dev/null @@ -1,347 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.virtualhost.plugins; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionConfiguration; -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -import java.util.concurrent.TimeUnit; - -/** - * Provide Unit Test coverage of the virtualhost SlowConsumer Configuration - * This is what controls how often the plugin will execute - */ -public class SlowConsumerDetectionConfigurationTest extends InternalBrokerBaseCase -{ - - /** - * Default Testing: - * - * Provide a fully complete and valid configuration specifying 'delay' and - * 'timeunit' and ensure that it is correctly processed. - * - * Ensure no exceptions are thrown and that we get the same values back that - * were put into the configuration. - */ - public void testConfigLoadingValidConfig() - { - SlowConsumerDetectionConfiguration config = new SlowConsumerDetectionConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - long DELAY=10; - String TIMEUNIT=TimeUnit.MICROSECONDS.toString(); - xmlconfig.addProperty("delay", String.valueOf(DELAY)); - xmlconfig.addProperty("timeunit", TIMEUNIT); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - } - catch (ConfigurationException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - - assertEquals("Delay not correctly returned.", DELAY, config.getDelay()); - assertEquals("TimeUnit not correctly returned.", - TIMEUNIT, String.valueOf(config.getTimeUnit())); - } - - /** - * Default Testing: - * - * Test Missing TimeUnit value gets default. - * - * The TimeUnit value is optional and default to SECONDS. - * - * Test that if we do not specify a TimeUnit then we correctly get seconds. - * - * Also verify that relying on the default does not impact the setting of - * the 'delay' value. - * - */ - public void testConfigLoadingMissingTimeUnitDefaults() - { - SlowConsumerDetectionConfiguration config = new SlowConsumerDetectionConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - long DELAY=10; - xmlconfig.addProperty("delay", String.valueOf(DELAY)); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - try - { - config.setConfiguration("", composite); - } - catch (ConfigurationException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - - assertEquals("Delay not correctly returned.", DELAY, config.getDelay()); - assertEquals("Default TimeUnit incorrect", TimeUnit.SECONDS, config.getTimeUnit()); - } - - /** - * Input Testing: - * - * TimeUnit parsing requires the String value be in UpperCase. - * Ensure we can handle when the user doesn't know this. - * - * Same test as 'testConfigLoadingValidConfig' but checking that - * the timeunit field is not case sensitive. - * i.e. the toUpper is being correctly applied. - */ - public void testConfigLoadingValidConfigStrangeTimeUnit() - { - SlowConsumerDetectionConfiguration config = new SlowConsumerDetectionConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - long DELAY=10; - - xmlconfig.addProperty("delay", DELAY); - xmlconfig.addProperty("timeunit", "MiCrOsEcOnDs"); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - } - catch (ConfigurationException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - - assertEquals("Delay not correctly returned.", DELAY, config.getDelay()); - assertEquals("TimeUnit not correctly returned.", - TimeUnit.MICROSECONDS.toString(), String.valueOf(config.getTimeUnit())); - - } - - /** - * Failure Testing: - * - * Test that delay must be long not a string value. - * Provide a delay as a written value not a long. 'ten'. - * - * This should throw a configuration exception which is being trapped and - * verified to be the right exception, a NumberFormatException. - * - */ - public void testConfigLoadingInValidDelayString() - { - SlowConsumerDetectionConfiguration config = new SlowConsumerDetectionConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - xmlconfig.addProperty("delay", "ten"); - xmlconfig.addProperty("timeunit", TimeUnit.MICROSECONDS.toString()); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - fail("Configuration should fail to validate"); - } - catch (ConfigurationException e) - { - Throwable cause = e.getCause(); - - assertEquals("Cause not correct", NumberFormatException.class, cause.getClass()); - } - } - - /** - * Failure Testing: - * - * Test that negative delays are invalid. - * - * Delay must be a positive value as negative delay means doesn't make sense. - * - * Configuration exception with a useful message should be thrown here. - * - */ - public void testConfigLoadingInValidDelayNegative() - { - SlowConsumerDetectionConfiguration config = new SlowConsumerDetectionConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - xmlconfig.addProperty("delay", "-10"); - xmlconfig.addProperty("timeunit", TimeUnit.MICROSECONDS.toString()); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - fail("Configuration should fail to validate"); - } - catch (ConfigurationException e) - { - Throwable cause = e.getCause(); - - assertNotNull("Configuration Exception must not be null.", cause); - assertEquals("Cause not correct", - ConfigurationException.class, cause.getClass()); - assertEquals("Incorrect message.", - "SlowConsumerDetectionConfiguration: 'delay' must be a Positive Long value.", - cause.getMessage()); - } - } - - /** - * Failure Testing: - * - * Test that delay cannot be 0. - * - * A zero delay means run constantly. This is not how VirtualHostTasks - * are designed to be run so we dis-allow the use of 0 delay. - * - * Same test as 'testConfigLoadingInValidDelayNegative' but with a 0 value. - * - */ - public void testConfigLoadingInValidDelayZero() - { - SlowConsumerDetectionConfiguration config = new SlowConsumerDetectionConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - xmlconfig.addProperty("delay", "0"); - xmlconfig.addProperty("timeunit", TimeUnit.MICROSECONDS.toString()); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - fail("Configuration should fail to validate"); - } - catch (ConfigurationException e) - { - Throwable cause = e.getCause(); - - assertNotNull("Configuration Exception must not be null.", cause); - assertEquals("Cause not correct", - ConfigurationException.class, cause.getClass()); - assertEquals("Incorrect message.", - "SlowConsumerDetectionConfiguration: 'delay' must be a Positive Long value.", - cause.getMessage()); - } - } - - /** - * Failure Testing: - * - * Test that missing delay fails. - * If we have no delay then we do not pick a default. So a Configuration - * Exception is thrown. - * - * */ - public void testConfigLoadingInValidMissingDelay() - { - SlowConsumerDetectionConfiguration config = new SlowConsumerDetectionConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - xmlconfig.addProperty("timeunit", TimeUnit.SECONDS.toString()); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - try - { - config.setConfiguration("", composite); - fail("Configuration should fail to validate"); - } - catch (ConfigurationException e) - { - assertEquals("Incorrect message.", "SlowConsumerDetectionConfiguration: unable to configure invalid delay:null", e.getMessage()); - } - } - - /** - * Failure Testing: - * - * Test that erroneous TimeUnit fails. - * - * Valid TimeUnit values vary based on the JVM version i.e. 1.6 added HOURS/DAYS etc. - * - * We don't test the values for TimeUnit are accepted other than MILLISECONDS in the - * positive testing at the start. - * - * Here we ensure that an erroneous for TimeUnit correctly throws an exception. - * - * We test with 'foo', which will never be a TimeUnit - * - */ - public void testConfigLoadingInValidTimeUnit() - { - SlowConsumerDetectionConfiguration config = new SlowConsumerDetectionConfiguration(); - - String TIMEUNIT = "foo"; - XMLConfiguration xmlconfig = new XMLConfiguration(); - - xmlconfig.addProperty("delay", "10"); - xmlconfig.addProperty("timeunit", TIMEUNIT); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - try - { - config.setConfiguration("", composite); - fail("Configuration should fail to validate"); - } - catch (ConfigurationException e) - { - assertEquals("Incorrect message.", "Unable to configure Slow Consumer Detection invalid TimeUnit:" + TIMEUNIT, e.getMessage()); - } - } - - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionPolicyConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionPolicyConfigurationTest.java deleted file mode 100644 index ea07632873..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionPolicyConfigurationTest.java +++ /dev/null @@ -1,105 +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.virtualhost.plugins; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionPolicyConfiguration; -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -/** - * Test class to ensure that the policy configuration can be processed. - */ -public class SlowConsumerDetectionPolicyConfigurationTest extends InternalBrokerBaseCase -{ - - /** - * Input Testing: - * - * Test that a given String can be set and retrieved through the configuration - * - * No validation is being performed to ensure that the policy exists. Only - * that a value can be set for the policy. - * - */ - public void testConfigLoadingValidConfig() - { - SlowConsumerDetectionPolicyConfiguration config = new SlowConsumerDetectionPolicyConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - String policyName = "TestPolicy"; - xmlconfig.addProperty("name", policyName); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - } - catch (ConfigurationException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - - assertEquals("Policy name not retrieved as expected.", - policyName, config.getPolicyName()); - } - - /** - * Failure Testing: - * - * Test that providing a configuration section without the 'name' field - * causes an exception to be thrown. - * - * An empty configuration is provided and the thrown exception message - * is checked to confirm the right reason. - * - */ - public void testConfigLoadingInValidConfig() - { - SlowConsumerDetectionPolicyConfiguration config = new SlowConsumerDetectionPolicyConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - fail("Config is invalid so won't validate."); - } - catch (ConfigurationException e) - { - e.printStackTrace(); - assertEquals("Exception message not as expected.", "No Slow consumer policy defined.", e.getMessage()); - } - } - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionQueueConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionQueueConfigurationTest.java deleted file mode 100644 index 96e524acf2..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetectionQueueConfigurationTest.java +++ /dev/null @@ -1,186 +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.virtualhost.plugins; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionQueueConfiguration; -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -/** - * Unit test the QueueConfiguration processing. - * - * This is slightly awkward as the {@link SlowConsumerDetectionQueueConfiguration} - * requries that a policy be available. - *

- * So all the Valid test much catch the ensuing {@link ConfigurationException} and - * validate that the error is due to a lack of a valid policy. - */ -public class SlowConsumerDetectionQueueConfigurationTest extends InternalBrokerBaseCase -{ - /** - * Test a fully loaded configuration file. - * - * It is not an error to have all control values specified. - *

- * Here we need to catch the {@link ConfigurationException} that ensues due to lack - * of a policy plugin. - */ - public void testConfigLoadingValidConfig() - { - SlowConsumerDetectionQueueConfiguration config = new SlowConsumerDetectionQueueConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - xmlconfig.addProperty("messageAge", "60000"); - xmlconfig.addProperty("depth", "1024"); - xmlconfig.addProperty("messageCount", "10"); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - fail("No Policies are avaialbe to load in a unit test"); - } - catch (ConfigurationException e) - { - assertTrue("Exception message incorrect, was: " + e.getMessage(), - e.getMessage().startsWith("No Slow Consumer Policy specified. Known Policies:[")); - } - } - - /** - * When we do not specify any control value then a {@link ConfigurationException} - * must be thrown to remind us. - */ - public void testConfigLoadingMissingConfig() - { - SlowConsumerDetectionQueueConfiguration config = new SlowConsumerDetectionQueueConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - fail("No Policies are avaialbe to load in a unit test"); - } - catch (ConfigurationException e) - { - - assertEquals("At least one configuration property('messageAge','depth'" + - " or 'messageCount') must be specified.", e.getMessage()); - } - } - - /** - * Setting messageAge on its own is enough to have a valid configuration - * - * Here we need to catch the {@link ConfigurationException} that ensues due to lack - * of a policy plugin. - */ - public void testConfigLoadingMessageAgeOk() - { - SlowConsumerDetectionQueueConfiguration config = new SlowConsumerDetectionQueueConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - xmlconfig.addProperty("messageAge", "60000"); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - fail("No Policies are avaialbe to load in a unit test"); - } - catch (ConfigurationException e) - { - assertTrue("Exception message incorrect, was: " + e.getMessage(), - e.getMessage().startsWith("No Slow Consumer Policy specified. Known Policies:[")); - } - } - - /** - * Setting depth on its own is enough to have a valid configuration. - * - * Here we need to catch the {@link ConfigurationException} that ensues due to lack - * of a policy plugin. - */ - public void testConfigLoadingDepthOk() - { - SlowConsumerDetectionQueueConfiguration config = new SlowConsumerDetectionQueueConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - xmlconfig.addProperty("depth", "1024"); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - fail("No Policies are avaialbe to load in a unit test"); - } - catch (ConfigurationException e) - { - assertTrue("Exception message incorrect, was: " + e.getMessage(), - e.getMessage().startsWith("No Slow Consumer Policy specified. Known Policies:[")); - } - } - - /** - * Setting messageCount on its own is enough to have a valid configuration. - * - * Here we need to catch the {@link ConfigurationException} that ensues due to lack - * of a policy plugin. - */ - public void testConfigLoadingMessageCountOk() - { - SlowConsumerDetectionQueueConfiguration config = new SlowConsumerDetectionQueueConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - xmlconfig.addProperty("messageCount", "10"); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("", composite); - fail("No Policies are avaialbe to load in a unit test"); - } - catch (ConfigurationException e) - { - assertTrue("Exception message incorrect, was: " + e.getMessage(), - e.getMessage().startsWith("No Slow Consumer Policy specified. Known Policies:[")); - } - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyConfigurationTest.java deleted file mode 100644 index f034d05c37..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyConfigurationTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.virtualhost.plugins.policies; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -/** - * Test to ensure TopicDelete Policy configuration can be loaded. - */ -public class TopicDeletePolicyConfigurationTest extends InternalBrokerBaseCase -{ - /** - * Test without any configuration being provided that the - * deletePersistent option is disabled. - */ - public void testNoConfigNoDeletePersistent() - { - TopicDeletePolicyConfiguration config = new TopicDeletePolicyConfiguration(); - - assertFalse("TopicDelete Configuration with no config should not delete persistent queues.", - config.deletePersistent()); - } - - /** - * Test that with the correct configuration the deletePersistent option can - * be enabled. - * - * Test creates a new Configuration object and passes in the xml snippet - * that the ConfigurationPlugin would receive during normal execution. - * This is the XML that would be matched for this plugin: - * - * - * - * - * So it would be subset and passed in as just: - * - * - * - * The property should therefore be enabled. - * - */ - public void testConfigDeletePersistent() - { - TopicDeletePolicyConfiguration config = new TopicDeletePolicyConfiguration(); - - XMLConfiguration xmlconfig = new XMLConfiguration(); - - xmlconfig.addProperty("delete-persistent",""); - - // Create a CompositeConfiguration as this is what the broker uses - CompositeConfiguration composite = new CompositeConfiguration(); - composite.addConfiguration(xmlconfig); - - try - { - config.setConfiguration("",composite); - } - catch (ConfigurationException e) - { - fail(e.getMessage()); - } - - assertTrue("A configured TopicDelete should delete persistent queues.", - config.deletePersistent()); - } - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java deleted file mode 100644 index aa8448b99d..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java +++ /dev/null @@ -1,294 +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.virtualhost.plugins.policies; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.exchange.DirectExchange; -import org.apache.qpid.server.exchange.TopicExchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.MockAMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; -import org.apache.qpid.server.virtualhost.VirtualHost; - -public class TopicDeletePolicyTest extends InternalBrokerBaseCase -{ - - private TopicDeletePolicyConfiguration _config; - - private VirtualHost _defaultVhost; - private InternalTestProtocolSession _connection; - - public void setUp() throws Exception - { - super.setUp(); - - _defaultVhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getDefaultVirtualHost(); - - _connection = new InternalTestProtocolSession(_defaultVhost); - - _config = new TopicDeletePolicyConfiguration(); - - XMLConfiguration config = new XMLConfiguration(); - - _config.setConfiguration("", config); - } - - private MockAMQQueue createOwnedQueue() - { - MockAMQQueue queue = new MockAMQQueue("testQueue"); - - _defaultVhost.getQueueRegistry().registerQueue(queue); - - try - { - AMQChannel channel = new AMQChannel(_connection, 0, null); - _connection.addChannel(channel); - - queue.setExclusiveOwningSession(channel); - } - catch (AMQException e) - { - fail("Unable to create Channel:" + e.getMessage()); - } - - return queue; - } - - private void setQueueToAutoDelete(final AMQQueue queue) - { - ((MockAMQQueue) queue).setAutoDelete(true); - - queue.setDeleteOnNoConsumers(true); - final AMQProtocolSession.Task deleteQueueTask = - new AMQProtocolSession.Task() - { - public void doTask(AMQProtocolSession session) throws AMQException - { - queue.delete(); - } - }; - - ((AMQChannel) queue.getExclusiveOwningSession()).getProtocolSession().addSessionCloseTask(deleteQueueTask); - } - - /** Check that a null queue passed in does not upset the policy. */ - public void testNullQueueParameter() throws ConfigurationException - { - TopicDeletePolicy policy = new TopicDeletePolicy(); - policy.configure(_config); - - try - { - policy.performPolicy(null); - } - catch (Exception e) - { - fail("Exception should not be thrown:" + e.getMessage()); - } - - } - - /** - * Set a owning Session to null which means this is not an exclusive queue - * so the queue should not be deleted - */ - public void testNonExclusiveQueue() - { - TopicDeletePolicy policy = new TopicDeletePolicy(); - policy.configure(_config); - - MockAMQQueue queue = createOwnedQueue(); - - queue.setExclusiveOwningSession(null); - - policy.performPolicy(queue); - - assertFalse("Queue should not be deleted", queue.isDeleted()); - assertFalse("Connection should not be closed", _connection.isClosed()); - } - - /** - * Test that exclusive JMS Queues are not deleted. - * Bind the queue to the direct exchange (so it is a JMS Queue). - * - * JMS Queues are not to be processed so this should not delete the queue. - */ - public void testQueuesAreNotProcessed() - { - TopicDeletePolicy policy = new TopicDeletePolicy(); - policy.configure(_config); - - MockAMQQueue queue = createOwnedQueue(); - - queue.addBinding(new Binding(null, null, "bindingKey", queue, new DirectExchange(), null)); - - policy.performPolicy(queue); - - assertFalse("Queue should not be deleted", queue.isDeleted()); - assertFalse("Connection should not be closed", _connection.isClosed()); - } - - /** - * Give a non auto-delete queue is bound to the topic exchange the - * TopicDeletePolicy will close the connection and delete the queue, - */ - public void testNonAutoDeleteTopicIsNotClosed() - { - TopicDeletePolicy policy = new TopicDeletePolicy(); - policy.configure(_config); - - MockAMQQueue queue = createOwnedQueue(); - - queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); - - queue.setAutoDelete(false); - - policy.performPolicy(queue); - - assertFalse("Queue should not be deleted", queue.isDeleted()); - assertTrue("Connection should be closed", _connection.isClosed()); - } - - /** - * Give a auto-delete queue bound to the topic exchange the TopicDeletePolicy will - * close the connection and delete the queue - */ - public void testTopicIsClosed() - { - TopicDeletePolicy policy = new TopicDeletePolicy(); - policy.configure(_config); - - final MockAMQQueue queue = createOwnedQueue(); - - queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); - - setQueueToAutoDelete(queue); - - policy.performPolicy(queue); - - assertTrue("Queue should be deleted", queue.isDeleted()); - assertTrue("Connection should be closed", _connection.isClosed()); - } - - /** - * Give a queue bound to the topic exchange the TopicDeletePolicy will - * close the connection and NOT delete the queue - */ - public void testNonAutoDeleteTopicIsClosedNotDeleted() - { - TopicDeletePolicy policy = new TopicDeletePolicy(); - policy.configure(_config); - - MockAMQQueue queue = createOwnedQueue(); - - queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); - - policy.performPolicy(queue); - - assertFalse("Queue should not be deleted", queue.isDeleted()); - assertTrue("Connection should be closed", _connection.isClosed()); - } - - /** - * Give a queue bound to the topic exchange the TopicDeletePolicy suitably - * configured with the delete-persistent tag will close the connection - * and delete the queue - */ - public void testPersistentTopicIsClosedAndDeleted() - { - //Set the config to delete persistent queues - _config.getConfig().addProperty("delete-persistent", ""); - - TopicDeletePolicy policy = new TopicDeletePolicy(); - policy.configure(_config); - - assertTrue("Config was not updated to delete Persistent topics", - _config.deletePersistent()); - - MockAMQQueue queue = createOwnedQueue(); - - queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); - - policy.performPolicy(queue); - - assertTrue("Queue should be deleted", queue.isDeleted()); - assertTrue("Connection should be closed", _connection.isClosed()); - } - - /** - * Give a queue bound to the topic exchange the TopicDeletePolicy not - * configured to close a persistent queue - */ - public void testPersistentTopicIsClosedAndDeletedNullConfig() - { - TopicDeletePolicy policy = new TopicDeletePolicy(); - // Explicity say we are not configuring the policy. - policy.configure(null); - - MockAMQQueue queue = createOwnedQueue(); - - queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); - - policy.performPolicy(queue); - - assertFalse("Queue should not be deleted", queue.isDeleted()); - assertTrue("Connection should be closed", _connection.isClosed()); - } - - public void testNonExclusiveQueueNullConfig() - { - _config = null; - testNonExclusiveQueue(); - } - - public void testQueuesAreNotProcessedNullConfig() - { - _config = null; - testQueuesAreNotProcessed(); - } - - public void testNonAutoDeleteTopicIsNotClosedNullConfig() - { - _config = null; - testNonAutoDeleteTopicIsNotClosed(); - } - - public void testTopicIsClosedNullConfig() - { - _config = null; - testTopicIsClosed(); - } - - public void testNonAutoDeleteTopicIsClosedNotDeletedNullConfig() throws AMQException - { - _config = null; - testNonAutoDeleteTopicIsClosedNotDeleted(); - } - -} diff --git a/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm b/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm index 02bf155c44..cddfcfb581 100644 --- a/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm +++ b/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm @@ -23,8 +23,8 @@ package ${package}; import static org.apache.qpid.server.logging.AbstractRootMessageLogger.DEFAULT_LOG_HIERARCHY_PREFIX; import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.logging.LogMessage; -import org.apache.qpid.server.registry.ApplicationRegistry; import java.text.MessageFormat; import java.util.Locale; @@ -44,7 +44,7 @@ import java.util.ResourceBundle; public class ${type.name}Messages { private static ResourceBundle _messages; - private static Locale _currentLocale; + private static Locale _currentLocale = BrokerProperties.getLocale(); public static final String ${type.name.toUpperCase()}_LOG_HIERARCHY = DEFAULT_LOG_HIERARCHY_PREFIX + "${type.name.toLowerCase()}"; #foreach( $message in ${type.list} ) @@ -58,24 +58,9 @@ public class ${type.name}Messages Logger.getLogger(${message.methodName.toUpperCase()}_LOG_HIERARCHY); #end - reload(); - } - - public static void reload() - { - if (ApplicationRegistry.isConfigured()) - { - _currentLocale = ApplicationRegistry.getInstance().getConfiguration().getLocale(); - } - else - { - _currentLocale = Locale.getDefault(); - } - _messages = ResourceBundle.getBundle("${resource}", _currentLocale); } - ## ## The list stored under key 'list' in the 'type' HashMap contains all the ## log messages that this class should contain. So for each entry in the list diff --git a/java/build.deps b/java/build.deps index 4742ec1a8c..f60ffd8ff8 100644 --- a/java/build.deps +++ b/java/build.deps @@ -59,10 +59,6 @@ servlet-api=${geronimo-servlet} dojo=lib/required/dojo-war-1.7.2.war -felix-main=lib/required/org.apache.felix.main-2.0.5.jar - -felix.libs=${felix-main} - jackson-core=lib/required/jackson-core-asl-1.9.0.jar jackson-mapper=lib/required/jackson-mapper-asl-1.9.0.jar @@ -72,19 +68,20 @@ commons-configuration.libs = ${commons-beanutils-core} ${commons-digester} \ common.libs=${slf4j-api} client.libs=${geronimo-jms} amqp-1-0-common.libs= -amqp-1-0-client.libs=${commons-cli} +amqp-1-0-client.libs= +amqp-1-0-client-example.libs=${commons-cli} amqp-1-0-client-jms.libs=${geronimo-jms} tools.libs=${commons-configuration.libs} ${log4j} broker.libs=${commons-cli} ${commons-logging} ${log4j} ${slf4j-log4j} \ - ${xalan} ${felix.libs} ${derby-db} ${commons-configuration.libs} \ + ${xalan} ${derby-db} ${commons-configuration.libs} \ ${jackson-core} ${jackson-mapper} ${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jetty-websocket} broker-plugins-management-http.libs=${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jackson-core} ${jackson-mapper} -broker-plugins.libs=${felix.libs} ${log4j} ${commons-configuration.libs} +broker-plugins.libs=${log4j} ${commons-configuration.libs} test.libs=${slf4j-log4j} ${log4j} ${junit} ${slf4j-api} ${mockito-all} -perftests.libs=${geronimo-jms} ${slf4j-api} ${log4j} ${slf4j-log4j} ${commons-logging} ${commons-collections} ${commons-beanutils-core} ${commons-lang} ${gson-all} +perftests.libs=${geronimo-jms} ${slf4j-api} ${log4j} ${slf4j-log4j} ${commons-logging} ${commons-collections} ${commons-beanutils-core} ${commons-lang} ${gson-all} ${derby-db} management-common.libs= @@ -93,11 +90,12 @@ broker.test.libs=${test.libs} client.test.libs=${test.libs} client-example.test.libs=${test.libs} tools.test.libs= -testkit.test.libs=${test.libs} systests.libs=${test.libs} perftests.test.libs=${test.libs} -broker-plugins.test.libs=${test.libs} +broker-plugins-access-control.test.libs=${test.libs} +broker-plugins-management-http.test.libs=${test.libs} +broker-plugins-management-jmx.test.libs=${test.libs} management-common.test.libs=${test.libs} @@ -117,10 +115,12 @@ bdbstore-jmx.test.libs=${test.libs} jfreechart.jar=lib/jfree/jfreechart-1.0.13.jar jcommon.jar=lib/jfree/jcommon-1.0.16.jar csvjdbc.jar=lib/csvjdbc/csvjdbc-1.0.8.jar -perftests-visualisation-jfc.libs=${jfreechart.jar} ${jcommon.jar} ${csvjdbc.jar} +perftests-visualisation-jfc.libs=${jfreechart.jar} ${jcommon.jar} ${csvjdbc.jar} ${derby-db} perftests-visualisation-jfc.test.libs=${test.libs} # Libraries used only within the build bnd=lib/required/bnd-0.0.384.jar jython=lib/required/jython-standalone-2.5.2.jar maven-ant-tasks=lib/required/maven-ant-tasks-2.1.1.jar +velocity.jar=lib/required/velocity-1.4.jar +velocity-dep.jar=lib/required/velocity-dep-1.4.jar diff --git a/java/build.xml b/java/build.xml index 7f51cb64c0..e3726d1c3c 100644 --- a/java/build.xml +++ b/java/build.xml @@ -32,7 +32,7 @@ - + @@ -77,6 +77,10 @@ + + + + diff --git a/java/client/build.xml b/java/client/build.xml index a02500d8e4..707bfda024 100644 --- a/java/client/build.xml +++ b/java/client/build.xml @@ -21,7 +21,7 @@ - + diff --git a/java/client/example/src/main/java/org/apache/qpid/example/Drain.java b/java/client/example/src/main/java/org/apache/qpid/example/Drain.java index 28e1d5a87e..f0eb83ad24 100644 --- a/java/client/example/src/main/java/org/apache/qpid/example/Drain.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/Drain.java @@ -88,7 +88,7 @@ public class Drain extends OptionParser } } } - + consumer.close(); ssn.close(); con.close(); } diff --git a/java/client/example/src/main/java/org/apache/qpid/example/ListReceiver.java b/java/client/example/src/main/java/org/apache/qpid/example/ListReceiver.java new file mode 100644 index 0000000000..b12cfab9de --- /dev/null +++ b/java/client/example/src/main/java/org/apache/qpid/example/ListReceiver.java @@ -0,0 +1,101 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.example; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.MapMessage; +import javax.jms.StreamMessage; +import javax.jms.MessageConsumer; +import javax.jms.Session; +import javax.jms.MessageEOFException; + +import org.apache.qpid.client.AMQAnyDestination; +import org.apache.qpid.client.AMQConnection; + +import org.apache.qpid.jms.ListMessage; + +import java.util.Enumeration; +import java.util.Iterator; + +public class ListReceiver { + + public static void main(String[] args) throws Exception + { + if (args.length != 1) { + System.out.println("Usage: java org.apache.qpid.example.ListReceiver <-l | -m | -s>"); + System.out.println("where:"); + System.out.println("\t-l\tAccept ListMessage and print it"); + System.out.println("\t-m\tAccept ListMessage as a MapMessage"); + System.out.println("\t-s\tAccept ListMessage as a StreamMessage"); + return; + } + + Connection connection = + new AMQConnection("amqp://guest:guest@test/?brokerlist='tcp://localhost:5672'"); + + connection.start(); + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Destination queue = new AMQAnyDestination("ADDR:message_queue; {create: always}"); + MessageConsumer consumer = session.createConsumer(queue); + + if (args[0].equals("-l")) { + System.out.println("Receiving as ListMessage"); + ListMessage m = (ListMessage)consumer.receive(); + System.out.println(m); + System.out.println("=========================================="); + System.out.println("Printing list contents:"); + Iterator i = m.iterator(); + while(i.hasNext()) + System.out.println(i.next()); + } + else if (args[0].equals("-m")) { + System.out.println("Receiving as MapMessage"); + MapMessage m = (MapMessage)consumer.receive(); + System.out.println(m); + System.out.println("=========================================="); + System.out.println("Printing map contents:"); + Enumeration keys = m.getMapNames(); + while(keys.hasMoreElements()) { + String key = (String)keys.nextElement(); + System.out.println(key + " => " + m.getObject(key)); + } + } + else if (args[0].equals("-s")) { + System.out.println("Receiving as StreamMessage"); + StreamMessage m = (StreamMessage)consumer.receive(); + System.out.println(m); + System.out.println("=========================================="); + System.out.println("Printing stream contents:"); + try { + while(true) + System.out.println(m.readObject()); + } + catch (MessageEOFException e) { + // DONE + } + } + + connection.close(); + } +} diff --git a/java/client/example/src/main/java/org/apache/qpid/example/ListSender.java b/java/client/example/src/main/java/org/apache/qpid/example/ListSender.java new file mode 100644 index 0000000000..fe2c1ec472 --- /dev/null +++ b/java/client/example/src/main/java/org/apache/qpid/example/ListSender.java @@ -0,0 +1,86 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.example; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.Message; +import javax.jms.MessageProducer; +import javax.jms.Session; + +import org.apache.qpid.client.AMQAnyDestination; +import org.apache.qpid.client.AMQConnection; + +import org.apache.qpid.jms.ListMessage; + + +public class ListSender { + + public static void main(String[] args) throws Exception + { + Connection connection = + new AMQConnection("amqp://guest:guest@test/?brokerlist='tcp://localhost:5672'"); + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + Destination queue = new AMQAnyDestination("ADDR:message_queue; {create: always}"); + MessageProducer producer = session.createProducer(queue); + + ListMessage m = ((org.apache.qpid.jms.Session)session).createListMessage(); + m.setIntProperty("Id", 987654321); + m.setStringProperty("name", "Widget"); + m.setDoubleProperty("price", 0.99); + + List colors = new ArrayList(); + colors.add("red"); + colors.add("green"); + colors.add("white"); + m.add(colors); + + Map dimensions = new HashMap(); + dimensions.put("length",10.2); + dimensions.put("width",5.1); + dimensions.put("depth",2.0); + m.add(dimensions); + + List> parts = new ArrayList>(); + parts.add(Arrays.asList(new Integer[] {1,2,5})); + parts.add(Arrays.asList(new Integer[] {8,2,5})); + m.add(parts); + + Map specs = new HashMap(); + specs.put("colours", colors); + specs.put("dimensions", dimensions); + specs.put("parts", parts); + m.add(specs); + + producer.send((Message)m); + System.out.println("Sent: " + m); + connection.close(); + } + +} diff --git a/java/client/example/src/main/java/org/apache/qpid/example/Spout.java b/java/client/example/src/main/java/org/apache/qpid/example/Spout.java index 61ff2dfc19..09e813f8c1 100644 --- a/java/client/example/src/main/java/org/apache/qpid/example/Spout.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/Spout.java @@ -100,6 +100,7 @@ public class Spout extends OptionParser System.out.println(msg); System.out.println("-------------------------------\n"); } + producer.close(); ssn.close(); con.close(); } diff --git a/java/client/src/main/java/client.bnd b/java/client/src/main/java/client.bnd index 4b9b191520..0a47b30c72 100755 --- a/java/client/src/main/java/client.bnd +++ b/java/client/src/main/java/client.bnd @@ -17,7 +17,7 @@ # under the License. # -ver: 0.19.0 +ver: 0.21.0 Bundle-SymbolicName: qpid-client Bundle-Version: ${ver} diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java index 89273599b9..597096db57 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java @@ -344,7 +344,14 @@ public class AMQBrokerDetails implements BrokerDetails optionsURL.append("='"); - optionsURL.append(_options.get(key)); + if (OPTIONS_TRUST_STORE_PASSWORD.equals(key) || OPTIONS_KEY_STORE_PASSWORD.equals(key)) + { + optionsURL.append("********"); + } + else + { + optionsURL.append(_options.get(key)); + } optionsURL.append("'"); diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java index d80858a7a1..9612417266 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java @@ -179,6 +179,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect // new amqp-0-10 encoded format. private boolean _useLegacyMapMessageFormat; + // Indicates whether to use the old stream message format or the + // new amqp-0-10 list encoded format. + private boolean _useLegacyStreamMessageFormat; + + // When sending to a Queue destination for the first time, check that the queue is bound + private final boolean _validateQueueOnSend; + //used to track the last failover time for //Address resolution purposes private volatile long _lastFailoverTime = 0; @@ -294,6 +301,30 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect _useLegacyMapMessageFormat = Boolean.getBoolean(ClientProperties.USE_LEGACY_MAP_MESSAGE_FORMAT); } + if (connectionURL.getOption(ConnectionURL.OPTIONS_USE_LEGACY_STREAM_MESSAGE_FORMAT) != null) + { + _useLegacyStreamMessageFormat = Boolean.parseBoolean( + connectionURL.getOption(ConnectionURL.OPTIONS_USE_LEGACY_STREAM_MESSAGE_FORMAT)); + } + else + { + // use the default value set for all connections + _useLegacyStreamMessageFormat = System.getProperty(ClientProperties.USE_LEGACY_STREAM_MESSAGE_FORMAT) == null ? + true : Boolean.getBoolean(ClientProperties.USE_LEGACY_STREAM_MESSAGE_FORMAT); + } + + if(connectionURL.getOption(ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND) != null) + { + _validateQueueOnSend = Boolean.parseBoolean( + connectionURL.getOption(ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND)); + } + else + { + _validateQueueOnSend = + Boolean.parseBoolean(System.getProperty(ClientProperties.VERIFY_QUEUE_ON_SEND, "false")); + } + + String amqpVersion = System.getProperty((ClientProperties.AMQP_VERSION), "0-10"); if (_logger.isDebugEnabled()) { @@ -1080,7 +1111,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect return _started; } - protected final boolean isConnected() + public final boolean isConnected() { return _connected; } @@ -1425,7 +1456,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect { return _delegate.getProtocolVersion(); } - + public String getBrokerUUID() { if(getProtocolVersion().equals(ProtocolVersion.v0_10)) @@ -1498,6 +1529,11 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect return _useLegacyMapMessageFormat; } + public boolean isUseLegacyStreamMessageFormat() + { + return _useLegacyStreamMessageFormat; + } + private void verifyClientID() throws AMQException { if (Boolean.getBoolean(ClientProperties.QPID_VERIFY_CLIENT_ID)) @@ -1539,4 +1575,14 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect + localAddress + " to " + remoteAddress); } } + + void setHeartbeatListener(HeartbeatListener listener) + { + _delegate.setHeartbeatListener(listener); + } + + public boolean validateQueueOnSend() + { + return _validateQueueOnSend; + } } diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java index b6f25a2cef..a8fdaeb65c 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate.java @@ -78,4 +78,6 @@ public interface AMQConnectionDelegate * @return true if the feature is supported by the server */ boolean isSupportedServerFeature(final String featureName); + + void setHeartbeatListener(HeartbeatListener listener); } diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java index 51e7e4153d..69e79d42a0 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_0_10.java @@ -33,6 +33,7 @@ import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ChannelLimitReachedException; +import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.jms.Session; import org.apache.qpid.properties.ConnectionStartProperties; import org.apache.qpid.protocol.AMQConstant; @@ -214,7 +215,8 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec + "********"); } - ConnectionSettings conSettings = retriveConnectionSettings(brokerDetail); + ConnectionSettings conSettings = retrieveConnectionSettings(brokerDetail); + _qpidConnection.setConnectionDelegate(new ClientConnectionDelegate(conSettings, _conn.getConnectionURL())); _qpidConnection.connect(conSettings); @@ -420,7 +422,13 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec return featureSupported; } - private ConnectionSettings retriveConnectionSettings(BrokerDetails brokerDetail) + @Override + public void setHeartbeatListener(HeartbeatListener listener) + { + ((ClientConnectionDelegate)(_qpidConnection.getConnectionDelegate())).setHeartbeatListener(listener); + } + + private ConnectionSettings retrieveConnectionSettings(BrokerDetails brokerDetail) { ConnectionSettings conSettings = brokerDetail.buildConnectionSettings(); @@ -442,6 +450,24 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec conSettings.setHeartbeatInterval(getHeartbeatInterval(brokerDetail)); + //Check connection-level ssl override setting + String connectionSslOption = _conn.getConnectionURL().getOption(ConnectionURL.OPTIONS_SSL); + if(connectionSslOption != null) + { + boolean connUseSsl = Boolean.parseBoolean(connectionSslOption); + boolean brokerlistUseSsl = conSettings.isUseSSL(); + + if( connUseSsl != brokerlistUseSsl) + { + conSettings.setUseSSL(connUseSsl); + + if (_logger.isDebugEnabled()) + { + _logger.debug("Applied connection ssl option override, setting UseSsl to: " + connUseSsl ); + } + } + } + return conSettings; } @@ -464,10 +490,14 @@ public class AMQConnectionDelegate_0_10 implements AMQConnectionDelegate, Connec heartbeat = Integer.getInteger(ClientProperties.IDLE_TIMEOUT_PROP_NAME)/1000; _logger.warn("JVM arg -Didle_timeout= is deprecated, please use -Dqpid.heartbeat="); } - else + else if(Integer.getInteger(ClientProperties.HEARTBEAT) != null) { heartbeat = Integer.getInteger(ClientProperties.HEARTBEAT,ClientProperties.HEARTBEAT_DEFAULT); } + else + { + heartbeat = Integer.getInteger("amqj.heartbeat.delay", ClientProperties.HEARTBEAT_DEFAULT); + } return heartbeat; } diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java index e1bf007e83..67d7c2a78c 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionDelegate_8_0.java @@ -40,6 +40,7 @@ import org.apache.qpid.framing.TxSelectBody; import org.apache.qpid.framing.TxSelectOkBody; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ChannelLimitReachedException; +import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.network.NetworkConnection; @@ -90,42 +91,43 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate public ProtocolVersion makeBrokerConnection(BrokerDetails brokerDetail) throws AMQException, IOException { + if (_logger.isDebugEnabled()) + { + _logger.debug("Connecting to broker:" + brokerDetail); + } final Set openOrClosedStates = EnumSet.of(AMQState.CONNECTION_OPEN, AMQState.CONNECTION_CLOSED); - - StateWaiter waiter = _conn.getProtocolHandler().createWaiter(openOrClosedStates); - ConnectionSettings settings = brokerDetail.buildConnectionSettings(); settings.setProtocol(brokerDetail.getTransport()); - SSLContext sslContext = null; - if (settings.isUseSSL()) + //Check connection-level ssl override setting + String connectionSslOption = _conn.getConnectionURL().getOption(ConnectionURL.OPTIONS_SSL); + if(connectionSslOption != null) { - try - { - sslContext = SSLContextFactory.buildClientContext( - settings.getTrustStorePath(), - settings.getTrustStorePassword(), - settings.getTrustStoreType(), - settings.getTrustManagerFactoryAlgorithm(), - settings.getKeyStorePath(), - settings.getKeyStorePassword(), - settings.getKeyStoreType(), - settings.getKeyManagerFactoryAlgorithm(), - settings.getCertAlias()); - } - catch (GeneralSecurityException e) + boolean connUseSsl = Boolean.parseBoolean(connectionSslOption); + boolean brokerlistUseSsl = settings.isUseSSL(); + + if( connUseSsl != brokerlistUseSsl) { - throw new AMQException("Unable to create SSLContext: " + e.getMessage(), e); + settings.setUseSSL(connUseSsl); + + if (_logger.isDebugEnabled()) + { + _logger.debug("Applied connection ssl option override, setting UseSsl to: " + connUseSsl ); + } } } SecurityLayer securityLayer = SecurityLayerFactory.newInstance(settings); OutgoingNetworkTransport transport = Transport.getOutgoingTransportInstance(getProtocolVersion()); - NetworkConnection network = transport.connect(settings, securityLayer.receiver(_conn.getProtocolHandler()), sslContext); + + NetworkConnection network = transport.connect(settings, securityLayer.receiver(_conn.getProtocolHandler()), + _conn.getProtocolHandler()); _conn.getProtocolHandler().setNetworkConnection(network, securityLayer.sender(network.getSender())); + + StateWaiter waiter = _conn.getProtocolHandler().createWaiter(openOrClosedStates); _conn.getProtocolHandler().getProtocolSession().init(); // this blocks until the connection has been set up or when an error // has prevented the connection being set up @@ -376,4 +378,10 @@ public class AMQConnectionDelegate_8_0 implements AMQConnectionDelegate // we just hardcode JMS selectors as supported. return ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR.equals(featureName); } + + @Override + public void setHeartbeatListener(HeartbeatListener listener) + { + _conn.getProtocolHandler().setHeartbeatListener(listener); + } } diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java index 8bc815d98e..a2d4b5ee17 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java @@ -140,7 +140,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF { try { - ConnectionURL connectionDetails = new AMQConnectionURL(_connectionDetails.toString()); + ConnectionURL connectionDetails = new AMQConnectionURL(_connectionDetails.getURL()); connectionDetails.setUsername(userName); connectionDetails.setPassword(password); diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java index 530186b1f9..f14b6d810b 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java @@ -52,6 +52,12 @@ public abstract class AMQDestination implements Destination, Referenceable private AMQShortString _exchangeClass; + private boolean _exchangeAutoDelete; + + private boolean _exchangeDurable; + + private boolean _exchangeInternal; + private boolean _isDurable; private boolean _isExclusive; @@ -106,16 +112,6 @@ public abstract class AMQDestination implements Destination, Referenceable _name = name; } - protected Link getTargetLink() - { - return _targetLink; - } - - protected void setTargetLink(Link targetLink) - { - _targetLink = targetLink; - } - // ----- Fields required to support new address syntax ------- public enum DestSyntax { @@ -180,10 +176,9 @@ public abstract class AMQDestination implements Destination, Referenceable private AddressOption _assert = AddressOption.NEVER; private AddressOption _delete = AddressOption.NEVER; - private Node _targetNode; - private Node _sourceNode; - private Link _targetLink; + private Node _node; private Link _link; + // ----- / Fields required to support new address syntax ------- @@ -280,6 +275,9 @@ public abstract class AMQDestination implements Destination, Referenceable { _exchangeName = binding.getExchangeName(); _exchangeClass = binding.getExchangeClass(); + _exchangeDurable = Boolean.parseBoolean(binding.getOption(BindingURL.OPTION_EXCHANGE_DURABLE)); + _exchangeAutoDelete = Boolean.parseBoolean(binding.getOption(BindingURL.OPTION_EXCHANGE_AUTODELETE)); + _exchangeInternal = Boolean.parseBoolean(binding.getOption(BindingURL.OPTION_EXCHANGE_INTERNAL)); _isExclusive = Boolean.parseBoolean(binding.getOption(BindingURL.OPTION_EXCLUSIVE)); _isAutoDelete = Boolean.parseBoolean(binding.getOption(BindingURL.OPTION_AUTODELETE)); @@ -358,6 +356,10 @@ public abstract class AMQDestination implements Destination, Referenceable _destSyntax = DestSyntax.BURL; _browseOnly = browseOnly; _rejectBehaviour = null; + _exchangeAutoDelete = false; + _exchangeDurable = false; + _exchangeInternal = false; + if (_logger.isDebugEnabled()) { _logger.debug("Based on " + toString() + " the selected destination syntax is " + _destSyntax); @@ -412,6 +414,21 @@ public abstract class AMQDestination implements Destination, Referenceable return _exchangeClass; } + public boolean isExchangeDurable() + { + return _exchangeDurable; + } + + public boolean isExchangeAutoDelete() + { + return _exchangeAutoDelete; + } + + public boolean isExchangeInternal() + { + return _exchangeInternal; + } + public boolean isTopic() { return ExchangeDefaults.TOPIC_EXCHANGE_CLASS.equals(_exchangeClass); @@ -579,6 +596,27 @@ public abstract class AMQDestination implements Destination, Referenceable sb.append(URLHelper.DEFAULT_OPTION_SEPERATOR); } + if (_exchangeDurable) + { + sb.append(BindingURL.OPTION_EXCHANGE_DURABLE); + sb.append("='true'"); + sb.append(URLHelper.DEFAULT_OPTION_SEPERATOR); + } + + if (_exchangeAutoDelete) + { + sb.append(BindingURL.OPTION_EXCHANGE_AUTODELETE); + sb.append("='true'"); + sb.append(URLHelper.DEFAULT_OPTION_SEPERATOR); + } + + if (_exchangeInternal) + { + sb.append(BindingURL.OPTION_EXCHANGE_INTERNAL); + sb.append("='true'"); + sb.append(URLHelper.DEFAULT_OPTION_SEPERATOR); + } + //removeKey the last char '?' if there is no options , ',' if there are. sb.deleteCharAt(sb.length() - 1); url = sb.toString(); @@ -773,24 +811,14 @@ public abstract class AMQDestination implements Destination, Referenceable _delete = option; } - public Node getTargetNode() + public Node getNode() { - return _targetNode; + return _node; } - public void setTargetNode(Node node) + public void setNode(Node node) { - _targetNode = node; - } - - public Node getSourceNode() - { - return _sourceNode; - } - - public void setSourceNode(Node node) - { - _sourceNode = node; + _node = node; } public Link getLink() @@ -851,21 +879,11 @@ public abstract class AMQDestination implements Destination, Referenceable _browseOnly = _addrHelper.isBrowseOnly(); - _addressType = _addrHelper.getTargetNodeType(); - _targetNode = _addrHelper.getTargetNode(_addressType); - _sourceNode = _addrHelper.getSourceNode(_addressType); + _addressType = _addrHelper.getNodeType(); + _node = _addrHelper.getNode(); _link = _addrHelper.getLink(); } - // This method is needed if we didn't know the node type at the beginning. - // Therefore we have to query the broker to figure out the type. - // Once the type is known we look for the necessary properties. - public void rebuildTargetAndSourceNodes(int addressType) - { - _targetNode = _addrHelper.getTargetNode(addressType); - _sourceNode = _addrHelper.getSourceNode(addressType); - } - // ----- / new address syntax ----------- public boolean isBrowseOnly() @@ -900,8 +918,7 @@ public abstract class AMQDestination implements Destination, Referenceable dest.setDelete(_delete); dest.setBrowseOnly(_browseOnly); dest.setAddressType(_addressType); - dest.setTargetNode(_targetNode); - dest.setSourceNode(_sourceNode); + dest.setNode(_node); dest.setLink(_link); dest.setAddressResolved(_addressResolved.get()); return dest; @@ -935,6 +952,4 @@ public abstract class AMQDestination implements Destination, Referenceable { return _rejectBehaviour; } - - } diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java index 1468e90c4e..91a6389214 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java @@ -20,11 +20,6 @@ */ package org.apache.qpid.client; -import static org.apache.qpid.configuration.ClientProperties.DEFAULT_FLOW_CONTROL_WAIT_FAILURE; -import static org.apache.qpid.configuration.ClientProperties.DEFAULT_FLOW_CONTROL_WAIT_NOTIFY_PERIOD; -import static org.apache.qpid.configuration.ClientProperties.QPID_FLOW_CONTROL_WAIT_FAILURE; -import static org.apache.qpid.configuration.ClientProperties.QPID_FLOW_CONTROL_WAIT_NOTIFY_PERIOD; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,6 +35,7 @@ import org.apache.qpid.client.failover.FailoverProtectedOperation; import org.apache.qpid.client.failover.FailoverRetrySupport; import org.apache.qpid.client.message.AMQMessageDelegateFactory; import org.apache.qpid.client.message.AMQPEncodedMapMessage; +import org.apache.qpid.client.message.AMQPEncodedListMessage; import org.apache.qpid.client.message.AbstractJMSMessage; import org.apache.qpid.client.message.CloseConsumerMessage; import org.apache.qpid.client.message.JMSBytesMessage; @@ -49,14 +45,13 @@ import org.apache.qpid.client.message.JMSStreamMessage; import org.apache.qpid.client.message.JMSTextMessage; import org.apache.qpid.client.message.MessageFactoryRegistry; import org.apache.qpid.client.message.UnprocessedMessage; -import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.client.util.FlowControllingBlockingQueue; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.jms.Session; +import org.apache.qpid.jms.ListMessage; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.thread.Threading; import org.apache.qpid.transport.SessionException; @@ -122,27 +117,16 @@ public abstract class AMQSession(new FailoverProtectedOperation() { public Object execute() throws AMQException, FailoverException { - sendExchangeDeclare(name, type, protocolHandler, nowait); + sendExchangeDeclare(name, type, nowait, durable, autoDelete, internal); return null; } }, _connection).execute(); } - public abstract void sendExchangeDeclare(final AMQShortString name, final AMQShortString type, final AMQProtocolHandler protocolHandler, - final boolean nowait) throws AMQException, FailoverException; - - - void declareQueuePassive(AMQDestination queue) throws AMQException - { - declareQueue(queue,false,false,true); - } + public abstract void sendExchangeDeclare(final AMQShortString name, final AMQShortString type, final boolean nowait, + boolean durable, boolean autoDelete, boolean internal) throws AMQException, FailoverException; /** * Declares a queue for a JMS destination. @@ -2768,31 +2725,8 @@ public abstract class AMQSession( - new FailoverProtectedOperation() - { - public AMQShortString execute() throws AMQException, FailoverException - { - // Generate the queue name if the destination indicates that a client generated name is to be used. - if (amqd.isNameRequired()) - { - amqd.setQueueName(protocolHandler.generateQueueName()); - } - - sendQueueDeclare(amqd, protocolHandler, nowait, passive); - - return amqd.getAMQQueueName(); - } - }, _connection).execute(); - } - - public abstract void sendQueueDeclare(final AMQDestination amqd, final AMQProtocolHandler protocolHandler, - final boolean nowait, boolean passive) throws AMQException, FailoverException; + protected abstract AMQShortString declareQueue(final AMQDestination amqd, + final boolean noLocal, final boolean nowait, final boolean passive) throws AMQException; /** * Undeclares the specified queue. @@ -2845,21 +2779,6 @@ public abstract class AMQSession= System.currentTimeMillis() ) - { - - _flowControl.wait(_flowControlWaitPeriod); - if (_logger.isInfoEnabled()) - { - _logger.info("Message send delayed by " + (System.currentTimeMillis() + _flowControlWaitFailure - expiryTime)/1000 + "s due to broker enforced flow control"); - } - } - if(!_flowControl.getFlowControl()) - { - _logger.error("Message send failed due to timeout waiting on broker enforced flow control"); - throw new JMSException("Unable to send message for " + _flowControlWaitFailure /1000 + " seconds due to broker enforced flow control"); - } - } + /** + * Tests whether flow to this session is blocked. + * + * @return true if flow is blocked or false otherwise. + */ + public abstract boolean isFlowBlocked(); - } + public abstract void setFlowControl(final boolean active); public interface Dispatchable { diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java index 8a7c6b1a01..8490a724bf 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java @@ -17,6 +17,11 @@ */ package org.apache.qpid.client; +import static org.apache.qpid.transport.Option.BATCH; +import static org.apache.qpid.transport.Option.NONE; +import static org.apache.qpid.transport.Option.SYNC; +import static org.apache.qpid.transport.Option.UNRELIABLE; + import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; @@ -29,8 +34,10 @@ import java.util.Timer; import java.util.TimerTask; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedQueue; + import javax.jms.Destination; import javax.jms.JMSException; + import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQDestination.AddressOption; import org.apache.qpid.client.AMQDestination.Binding; @@ -44,18 +51,32 @@ import org.apache.qpid.client.message.MessageFactoryRegistry; import org.apache.qpid.client.message.UnprocessedMessage_0_10; import org.apache.qpid.client.messaging.address.AddressHelper; import org.apache.qpid.client.messaging.address.Link; -import org.apache.qpid.client.messaging.address.Node.ExchangeNode; -import org.apache.qpid.client.messaging.address.Node.QueueNode; -import org.apache.qpid.client.protocol.AMQProtocolHandler; +import org.apache.qpid.client.messaging.address.Link.SubscriptionQueue; +import org.apache.qpid.client.messaging.address.Node; +import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.transport.*; -import static org.apache.qpid.transport.Option.BATCH; -import static org.apache.qpid.transport.Option.NONE; -import static org.apache.qpid.transport.Option.SYNC; -import static org.apache.qpid.transport.Option.UNRELIABLE; +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.ExchangeBoundResult; +import org.apache.qpid.transport.ExchangeQueryResult; +import org.apache.qpid.transport.ExecutionErrorCode; +import org.apache.qpid.transport.ExecutionException; +import org.apache.qpid.transport.MessageAcceptMode; +import org.apache.qpid.transport.MessageAcquireMode; +import org.apache.qpid.transport.MessageCreditUnit; +import org.apache.qpid.transport.MessageFlowMode; +import org.apache.qpid.transport.MessageTransfer; +import org.apache.qpid.transport.Option; +import org.apache.qpid.transport.QueueQueryResult; +import org.apache.qpid.transport.Range; +import org.apache.qpid.transport.RangeSet; +import org.apache.qpid.transport.RangeSetFactory; +import org.apache.qpid.transport.Session; +import org.apache.qpid.transport.SessionException; +import org.apache.qpid.transport.SessionListener; +import org.apache.qpid.transport.TransportException; import org.apache.qpid.util.Serial; import org.apache.qpid.util.Strings; import org.slf4j.Logger; @@ -347,15 +368,22 @@ public class AMQSession_0_10 extends AMQSession bindings = new ArrayList(); - bindings.addAll(destination.getSourceNode().getBindings()); - bindings.addAll(destination.getTargetNode().getBindings()); + bindings.addAll(destination.getNode().getBindings()); String defaultExchange = destination.getAddressType() == AMQDestination.TOPIC_TYPE ? destination.getAddressName(): "amq.topic"; for (Binding binding: bindings) { + // Currently there is a bug (QPID-3317) with setting up and tearing down x-bindings for link. + // The null check below is a way to side step that issue while fixing QPID-4146 + // Note this issue only affects producers. + if (binding.getQueue() == null && queueName == null) + { + continue; + } String queue = binding.getQueue() == null? queueName.asString(): binding.getQueue(); @@ -523,11 +551,9 @@ public class AMQSession_0_10 extends AMQSession args) @@ -591,10 +617,22 @@ public class AMQSession_0_10 extends AMQSession args, - final boolean nowait) throws AMQException + final boolean nowait, boolean durable, boolean autoDelete) throws AMQException { getQpidSession().exchangeDeclare( name, type, alternateExchange, args, - name.toString().startsWith("amq.") ? Option.PASSIVE - : Option.NONE); + name.toString().startsWith("amq.") ? Option.PASSIVE : Option.NONE, + durable ? Option.DURABLE : Option.NONE, + autoDelete ? Option.AUTO_DELETE : Option.NONE); // We need to sync so that we get notify of an error. if (!nowait) { @@ -717,18 +750,8 @@ public class AMQSession_0_10 extends AMQSession arguments = new HashMap(); arguments.putAll((Map) node.getDeclareArgs()); if (arguments == null || arguments.get(AddressHelper.NO_LOCAL) == null) @@ -925,12 +949,11 @@ public class AMQSession_0_10 extends AMQSession( new FailoverProtectedOperation() { @@ -947,7 +970,7 @@ public class AMQSession_0_10 extends AMQSession arguments = queueProps.getDeclareArgs(); + if (!arguments.containsKey((AddressHelper.NO_LOCAL))) + { + arguments.put(AddressHelper.NO_LOCAL, noLocal); + } + + if (link.isDurable() && queueName.startsWith("TempQueue")) + { + throw new AMQException("You cannot mark a subscription queue as durable without providing a name for the link."); } - node.setExclusive(true); - node.setAutoDelete(!node.isDurable()); - send0_10QueueDeclare(dest,null,noLocal,true, false); - getQpidSession().exchangeBind(dest.getQueueName(), - dest.getAddressName(), - dest.getSubject(), - Collections.emptyMap()); - sendQueueBind(dest.getAMQQueueName(), dest.getRoutingKey(), - null,dest.getExchangeName(),dest, false); + + getQpidSession().queueDeclare(queueName, + queueProps.getAlternateExchange(), arguments, + queueProps.isAutoDelete() ? Option.AUTO_DELETE : Option.NONE, + link.isDurable() ? Option.DURABLE : Option.NONE, + queueProps.isExclusive() ? Option.EXCLUSIVE : Option.NONE); + + Map bindingArguments = new HashMap(); + bindingArguments.put(AMQPFilterTypes.JMS_SELECTOR.getValue().toString(), messageSelector == null ? "" : messageSelector); + getQpidSession().exchangeBind(queueName, + dest.getAddressName(), + dest.getSubject(), + bindingArguments); } - - public void setLegacyFiledsForQueueType(AMQDestination dest) + + public void setLegacyFieldsForQueueType(AMQDestination dest) { // legacy support dest.setQueueName(new AMQShortString(dest.getAddressName())); @@ -1345,7 +1367,7 @@ public class AMQSession_0_10 extends AMQSession arguments = node.getDeclareArgs(); + if (!arguments.containsKey((AddressHelper.NO_LOCAL))) + { + arguments.put(AddressHelper.NO_LOCAL, noLocal); + } + getQpidSession().queueDeclare(dest.getAddressName(), + node.getAlternateExchange(), arguments, + node.isAutoDelete() ? Option.AUTO_DELETE : Option.NONE, + node.isDurable() ? Option.DURABLE : Option.NONE, + node.isExclusive() ? Option.EXCLUSIVE : Option.NONE); + + createBindings(dest, dest.getNode().getBindings()); + sync(); + } + + void handleExchangeNodeCreation(AMQDestination dest) throws AMQException + { + Node node = dest.getNode(); + sendExchangeDeclare(dest.getAddressName(), + node.getExchangeType(), + node.getAlternateExchange(), + node.getDeclareArgs(), + false, + node.isDurable(), + node.isAutoDelete()); + + // If bindings are specified without a queue name and is called by the producer, + // the broker will send an exception as expected. + createBindings(dest, dest.getNode().getBindings()); + sync(); + } + + void handleLinkCreation(AMQDestination dest) throws AMQException + { + createBindings(dest, dest.getLink().getBindings()); + } + + void createBindings(AMQDestination dest, List bindings) + { + String defaultExchangeForBinding = dest.getAddressType() == AMQDestination.TOPIC_TYPE ? dest + .getAddressName() : "amq.topic"; + + String defaultQueueName = null; + if (AMQDestination.QUEUE_TYPE == dest.getAddressType()) + { + defaultQueueName = dest.getQueueName(); + } + else + { + defaultQueueName = dest.getLink().getName() != null ? dest.getLink().getName() : dest.getQueueName(); + } + + for (Binding binding: bindings) + { + String queue = binding.getQueue() == null? + defaultQueueName: binding.getQueue(); + + String exchange = binding.getExchange() == null ? + defaultExchangeForBinding : + binding.getExchange(); + + if (_logger.isDebugEnabled()) + { + _logger.debug("Binding queue : " + queue + + " exchange: " + exchange + + " using binding key " + binding.getBindingKey() + + " with args " + Strings.printMap(binding.getArgs())); + } + getQpidSession().exchangeBind(queue, + exchange, + binding.getBindingKey(), + binding.getArgs()); + } + } + + void handleLinkDelete(AMQDestination dest) throws AMQException + { + // We need to destroy link bindings + String defaultExchangeForBinding = dest.getAddressType() == AMQDestination.TOPIC_TYPE ? dest + .getAddressName() : "amq.topic"; + + String defaultQueueName = null; + if (AMQDestination.QUEUE_TYPE == dest.getAddressType()) + { + defaultQueueName = dest.getQueueName(); + } + else + { + defaultQueueName = dest.getLink().getName() != null ? dest.getLink().getName() : dest.getQueueName(); + } + + for (Binding binding: dest.getLink().getBindings()) + { + String queue = binding.getQueue() == null? + defaultQueueName: binding.getQueue(); + + String exchange = binding.getExchange() == null ? + defaultExchangeForBinding : + binding.getExchange(); + + if (_logger.isDebugEnabled()) + { + _logger.debug("Unbinding queue : " + queue + + " exchange: " + exchange + + " using binding key " + binding.getBindingKey() + + " with args " + Strings.printMap(binding.getArgs())); + } + getQpidSession().exchangeUnbind(queue, exchange, + binding.getBindingKey()); + } + } + + void deleteSubscriptionQueue(AMQDestination dest) throws AMQException + { + // We need to delete the subscription queue. + if (dest.getAddressType() == AMQDestination.TOPIC_TYPE && + dest.getLink().getSubscriptionQueue().isExclusive() && + isQueueExist(dest, false)) + { + getQpidSession().queueDelete(dest.getQueueName()); + } + } + + void handleNodeDelete(AMQDestination dest) throws AMQException + { + if (AMQDestination.TOPIC_TYPE == dest.getAddressType()) + { + if (isExchangeExist(dest,false)) + { + getQpidSession().exchangeDelete(dest.getAddressName()); + } + } + else + { + if (isQueueExist(dest,false)) + { + getQpidSession().queueDelete(dest.getAddressName()); + } + } + } +} diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java index 8ab23a240e..3097b33da3 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java @@ -21,12 +21,18 @@ package org.apache.qpid.client; +import static org.apache.qpid.configuration.ClientProperties.DEFAULT_FLOW_CONTROL_WAIT_FAILURE; +import static org.apache.qpid.configuration.ClientProperties.DEFAULT_FLOW_CONTROL_WAIT_NOTIFY_PERIOD; +import static org.apache.qpid.configuration.ClientProperties.QPID_FLOW_CONTROL_WAIT_FAILURE; +import static org.apache.qpid.configuration.ClientProperties.QPID_FLOW_CONTROL_WAIT_NOTIFY_PERIOD; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.qpid.AMQException; import org.apache.qpid.AMQUndeliveredException; import org.apache.qpid.client.failover.FailoverException; +import org.apache.qpid.client.failover.FailoverNoopSupport; import org.apache.qpid.client.failover.FailoverProtectedOperation; import org.apache.qpid.client.failover.FailoverRetrySupport; import org.apache.qpid.client.message.AMQMessageDelegateFactory; @@ -58,6 +64,27 @@ public class AMQSession_0_8 extends AMQSession( + new FailoverProtectedOperation() + { + public AMQShortString execute() throws AMQException, FailoverException + { + // Generate the queue name if the destination indicates that a client generated name is to be used. + if (amqd.isNameRequired()) + { + amqd.setQueueName(protocolHandler.generateQueueName()); + } + + sendQueueDeclare(amqd, passive); + + return amqd.getAMQQueueName(); + } + }, getAMQConnection()).execute(); } public void sendQueueDelete(final AMQShortString queueName) throws AMQException, FailoverException @@ -440,10 +508,8 @@ public class AMQSession_0_8 extends AMQSession= System.currentTimeMillis() ) + { + + _flowControl.wait(_flowControlWaitPeriod); + if (_logger.isInfoEnabled()) + { + _logger.info("Message send delayed by " + (System.currentTimeMillis() + _flowControlWaitFailure - expiryTime)/1000 + "s due to broker enforced flow control"); + } + } + if(!_flowControl.getFlowControl()) + { + _logger.error("Message send failed due to timeout waiting on broker enforced flow control"); + throw new JMSException("Unable to send message for " + _flowControlWaitFailure /1000 + " seconds due to broker enforced flow control"); + } + } + } + + + public abstract static class DestinationCache { private final Map> cache = new HashMap>(); @@ -740,6 +857,22 @@ public class AMQSession_0_8 extends AMQSession extends Closeable implements Messa private final AMQSession _session; - private final AMQProtocolHandler _protocolHandler; - /** * We need to store the "raw" field table so that we can resubscribe in the event of failover being required */ @@ -140,9 +137,9 @@ public abstract class BasicMessageConsumer extends Closeable implements Messa protected BasicMessageConsumer(int channelId, AMQConnection connection, AMQDestination destination, String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory, - AMQSession session, AMQProtocolHandler protocolHandler, - FieldTable rawSelector, int prefetchHigh, int prefetchLow, - boolean exclusive, int acknowledgeMode, boolean browseOnly, boolean autoClose) throws JMSException + AMQSession session, FieldTable rawSelector, + int prefetchHigh, int prefetchLow, boolean exclusive, + int acknowledgeMode, boolean browseOnly, boolean autoClose) throws JMSException { _channelId = channelId; _connection = connection; @@ -150,7 +147,6 @@ public abstract class BasicMessageConsumer extends Closeable implements Messa _destination = destination; _messageFactory = messageFactory; _session = session; - _protocolHandler = protocolHandler; _prefetchHigh = prefetchHigh; _prefetchLow = prefetchLow; _exclusive = exclusive; @@ -597,7 +593,6 @@ public abstract class BasicMessageConsumer extends Closeable implements Messa { sendCancel(); } - cleanupQueue(); } } catch (AMQException e) @@ -635,8 +630,6 @@ public abstract class BasicMessageConsumer extends Closeable implements Messa } abstract void sendCancel() throws AMQException, FailoverException; - - abstract void cleanupQueue() throws AMQException, FailoverException; /** * Called when you need to invalidate a consumer. Used for example when failover has occurred and the client has @@ -1042,10 +1035,4 @@ public abstract class BasicMessageConsumer extends Closeable implements Messa { return _messageFactory; } - - protected AMQProtocolHandler getProtocolHandler() - { - return _protocolHandler; - } - } diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java index 26bb51b821..ef7b8cc217 100644 --- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java @@ -28,7 +28,6 @@ import org.apache.qpid.client.message.AMQMessageDelegate_0_10; import org.apache.qpid.client.message.AbstractJMSMessage; import org.apache.qpid.client.message.MessageFactoryRegistry; import org.apache.qpid.client.message.UnprocessedMessage_0_10; -import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.common.ServerPropertyNames; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.jms.Session; @@ -82,13 +81,13 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer session, AMQProtocolHandler protocolHandler, - FieldTable rawSelector, int prefetchHigh, int prefetchLow, - boolean exclusive, int acknowledgeMode, boolean browseOnly, boolean autoClose) + AMQSession session, FieldTable rawSelector, + int prefetchHigh, int prefetchLow, boolean exclusive, + int acknowledgeMode, boolean browseOnly, boolean autoClose) throws JMSException { - super(channelId, connection, destination, messageSelector, noLocal, messageFactory, session, protocolHandler, - rawSelector, prefetchHigh, prefetchLow, exclusive, acknowledgeMode, browseOnly, autoClose); + super(channelId, connection, destination, messageSelector, noLocal, messageFactory, session, rawSelector, + prefetchHigh, prefetchLow, exclusive, acknowledgeMode, browseOnly, autoClose); _0_10session = (AMQSession_0_10) session; _serverJmsSelectorSupport = connection.isSupportedServerFeature(ServerPropertyNames.FEATURE_QPID_JMS_SELECTOR); @@ -96,6 +95,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer { @@ -91,18 +95,24 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener sender = session.getSender(); if (error != null) { session.notifyError(error); - } - - // Close the protocol Session, including any open TCP connections - session.closeProtocolSession(); + } - // Closing the session should not introduce a race condition as this thread will continue to propgate any - // exception in to the exceptionCaught method of the SessionHandler. - // Any sessionClosed event should occur after this. + // Close the open TCP connection + try + { + sender.close(); + } + catch(TransportException e) + { + //Ignore, they are already logged by the Sender and this + //is a connection-close being processed by the IoReceiver + //which will as it closes initiate failover if necessary. + } } } diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java index a0c3914127..94b835dd1a 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java @@ -91,6 +91,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate private MessageProperties _messageProps; private DeliveryProperties _deliveryProps; + private String _messageID; protected AMQMessageDelegate_0_10() { @@ -171,8 +172,12 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate public String getJMSMessageID() throws JMSException { - UUID id = _messageProps.getMessageId(); - return id == null ? null : "ID:" + id; + if (_messageID == null && _messageProps.getMessageId() != null) + { + UUID id = _messageProps.getMessageId(); + _messageID = "ID:" + id; + } + return _messageID; } public void setJMSMessageID(String messageId) throws JMSException @@ -185,14 +190,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate { if(messageId.startsWith("ID:")) { - try - { - _messageProps.setMessageId(UUID.fromString(messageId.substring(3))); - } - catch(IllegalArgumentException ex) - { - throw new JMSException("MessageId '"+messageId+"' is not of the correct format, it must be ID: followed by a UUID"); - } + _messageID = messageId; } else { @@ -201,6 +199,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate } } + /* Used by the internal implementation */ public void setJMSMessageID(UUID messageId) throws JMSException { if(messageId == null) @@ -344,7 +343,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate int type = ((AMQSession_0_10)getAMQSession()).resolveAddressType(amqd); if (type == AMQDestination.QUEUE_TYPE) { - ((AMQSession_0_10)getAMQSession()).setLegacyFiledsForQueueType(amqd); + ((AMQSession_0_10)getAMQSession()).setLegacyFieldsForQueueType(amqd); } else { diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedListMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedListMessage.java new file mode 100644 index 0000000000..1d2cb43322 --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedListMessage.java @@ -0,0 +1,935 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * + */ +package org.apache.qpid.client.message; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.qpid.AMQException; + +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.transport.codec.BBEncoder; + +import javax.jms.JMSException; +import javax.jms.MessageFormatException; +import javax.jms.MessageEOFException; +import java.lang.NumberFormatException; +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class AMQPEncodedListMessage extends JMSStreamMessage implements + org.apache.qpid.jms.ListMessage, javax.jms.MapMessage +{ + private static final Logger _logger = LoggerFactory + .getLogger(AMQPEncodedListMessage.class); + + public static final String MIME_TYPE = "amqp/list"; + + private List _list = new ArrayList(); + + public AMQPEncodedListMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException + { + super(delegateFactory); + currentIndex = 0; + } + + AMQPEncodedListMessage(AMQMessageDelegate delegate, ByteBuffer data) + throws AMQException + { + super(delegate, data); + if (data != null) + { + try + { + populateListFromData(data); + } + catch (JMSException je) + { + throw new AMQException(null, + "Error populating ListMessage from ByteBuffer", je); + } + } + currentIndex = 0; + } + + public String toBodyString() throws JMSException + { + return _list == null ? "" : _list.toString(); + } + + protected String getMimeType() + { + return MIME_TYPE; + } + + /* ListMessage Implementation. */ + public boolean add(Object a) throws JMSException + { + checkWritable(); + checkAllowedValue(a); + try + { + return _list.add(a); + } + catch (Exception e) + { + MessageFormatException ex = new MessageFormatException("Error adding to ListMessage"); + ex.initCause(e); + ex.setLinkedException(e); + throw ex; + + } + } + + public void add(int index, Object element) throws JMSException + { + checkWritable(); + checkAllowedValue(element); + try + { + _list.add(index, element); + } + catch (Exception e) + { + MessageFormatException ex = new MessageFormatException("Error adding to ListMessage at " + + index); + ex.initCause(e); + ex.setLinkedException(e); + throw ex; + } + } + + public boolean contains(Object o) throws JMSException + { + try + { + return _list.contains(o); + } + catch (Exception e) + { + JMSException ex = new JMSException("Error when looking up object"); + ex.initCause(e); + ex.setLinkedException(e); + throw ex; + } + } + + public Object get(int index) throws JMSException + { + try + { + return _list.get(index); + } + catch (IndexOutOfBoundsException e) + { + MessageFormatException ex = new MessageFormatException( + "Error getting ListMessage element at " + index); + ex.initCause(e); + ex.setLinkedException(e); + throw ex; + } + } + + public int indexOf(Object o) + { + return _list.indexOf(o); + } + + public Iterator iterator() + { + return _list.iterator(); + } + + public Object remove(int index) throws JMSException + { + checkWritable(); + try + { + return _list.remove(index); + } + catch (IndexOutOfBoundsException e) + { + MessageFormatException ex = new MessageFormatException( + "Error removing ListMessage element at " + index); + ex.initCause(e); + ex.setLinkedException(e); + throw ex; + } + } + + public boolean remove(Object o) throws JMSException + { + checkWritable(); + return _list.remove(o); + } + + public Object set(int index, Object element) throws JMSException + { + checkWritable(); + checkAllowedValue(element); + try + { + return _list.set(index, element); + } + catch (Exception e) + { + MessageFormatException ex = new MessageFormatException( + "Error setting ListMessage element at " + index); + ex.initCause(e); + ex.setLinkedException(e); + throw ex; + } + } + + public int size() + { + return _list.size(); + } + + public Object[] toArray() + { + return _list.toArray(); + } + + /* MapMessage Implementation */ + private boolean isValidIndex(int index) + { + if (index >= 0 && index < size()) + return true; + + return false; + } + + private int getValidIndex(String indexStr) throws JMSException + { + if ((indexStr == null) || indexStr.equals("")) + { + throw new IllegalArgumentException( + "Property name cannot be null, or the empty String."); + } + + int index = 0; + try + { + index = Integer.parseInt(indexStr); + } + catch (NumberFormatException e) + { + JMSException ex = new JMSException("Invalid index string"); + ex.initCause(e); + ex.setLinkedException(e); + throw ex; + } + if (isValidIndex(index)) + return index; + + throw new MessageFormatException("Property " + indexStr + + " should be a valid index into the list of size " + size()); + } + + private void setGenericForMap(String propName, Object o) + throws JMSException + { + checkWritable(); + int index = 0; + try + { + index = Integer.parseInt(propName); + } + catch (NumberFormatException e) + { + JMSException ex = new JMSException("The property name should be a valid index"); + ex.initCause(e); + ex.setLinkedException(e); + throw ex; + } + + if (isValidIndex(index)) + remove(index); + add(index, o); + } + + public boolean getBoolean(String propName) throws JMSException + { + return getBooleanImpl(getValidIndex(propName)); + } + + public byte getByte(String propName) throws JMSException + { + return getByteImpl(getValidIndex(propName)); + } + + public short getShort(String propName) throws JMSException + { + return getShortImpl(getValidIndex(propName)); + } + + public int getInt(String propName) throws JMSException + { + return getIntImpl(getValidIndex(propName)); + } + + public long getLong(String propName) throws JMSException + { + return getLongImpl(getValidIndex(propName)); + } + + public char getChar(String propName) throws JMSException + { + return getCharImpl(getValidIndex(propName)); + + } + + public float getFloat(String propName) throws JMSException + { + return getFloatImpl(getValidIndex(propName)); + } + + public double getDouble(String propName) throws JMSException + { + return getDoubleImpl(getValidIndex(propName)); + } + + public String getString(String propName) throws JMSException + { + return getStringImpl(getValidIndex(propName)); + } + + public byte[] getBytes(String propName) throws JMSException + { + return getBytesImpl(getValidIndex(propName)); + } + + public Object getObject(String propName) throws JMSException + { + return get(getValidIndex(propName)); + } + + public Enumeration getMapNames() throws JMSException + { + List names = new ArrayList(); + int i = 0; + + while (i < size()) + names.add(Integer.toString(i++)); + + return Collections.enumeration(names); + } + + public void setBoolean(String propName, boolean b) throws JMSException + { + setGenericForMap(propName, b); + } + + public void setByte(String propName, byte b) throws JMSException + { + setGenericForMap(propName, b); + } + + public void setShort(String propName, short i) throws JMSException + { + setGenericForMap(propName, i); + } + + public void setChar(String propName, char c) throws JMSException + { + setGenericForMap(propName, c); + } + + public void setInt(String propName, int i) throws JMSException + { + setGenericForMap(propName, i); + } + + public void setLong(String propName, long l) throws JMSException + { + setGenericForMap(propName, l); + } + + public void setFloat(String propName, float v) throws JMSException + { + setGenericForMap(propName, v); + } + + public void setDouble(String propName, double v) throws JMSException + { + setGenericForMap(propName, v); + } + + public void setString(String propName, String string1) throws JMSException + { + setGenericForMap(propName, string1); + } + + public void setBytes(String propName, byte[] bytes) throws JMSException + { + setGenericForMap(propName, bytes); + } + + public void setBytes(String propName, byte[] bytes, int offset, int length) + throws JMSException + { + if ((offset == 0) && (length == bytes.length)) + { + setBytes(propName, bytes); + } + else + { + byte[] newBytes = new byte[length]; + System.arraycopy(bytes, offset, newBytes, 0, length); + setBytes(propName, newBytes); + } + } + + public void setObject(String propName, Object value) throws JMSException + { + checkAllowedValue(value); + setGenericForMap(propName, value); + } + + public boolean itemExists(String propName) throws JMSException + { + return isValidIndex(Integer.parseInt(propName)); + } + + // StreamMessage methods + + private int currentIndex; + + private static final String MESSAGE_EOF_EXCEPTION = "End of Stream (ListMessage) at index: "; + + private void setGenericForStream(Object o) throws JMSException + { + checkWritable(); + add(o); + currentIndex++; + } + + @Override + public boolean readBoolean() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return getBooleanImpl(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public byte readByte() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return getByteImpl(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public int readBytes(byte[] value) throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + { + ByteBuffer res = ByteBuffer.wrap(getBytesImpl(currentIndex++)); + res.get(value); + return value.length; + } + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public char readChar() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return getCharImpl(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public double readDouble() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return getDoubleImpl(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public float readFloat() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return getFloatImpl(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public int readInt() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return getIntImpl(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public long readLong() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return getLongImpl(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public Object readObject() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return get(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public short readShort() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return getShortImpl(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public String readString() throws JMSException + { + checkReadable(); + if (isValidIndex(currentIndex)) + return getStringImpl(currentIndex++); + + throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex); + } + + @Override + public void writeBoolean(boolean value) throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeByte(byte value) throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeBytes(byte[] value) throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeBytes(byte[] value, int offset, int length) + throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeChar(char value) throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeDouble(double value) throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeFloat(float value) throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeInt(int value) throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeLong(long value) throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeObject(Object value) throws JMSException + { + checkAllowedValue(value); + setGenericForStream(value); + } + + @Override + public void writeShort(short value) throws JMSException + { + setGenericForStream(value); + } + + @Override + public void writeString(String value) throws JMSException + { + setGenericForStream(value); + } + + // Common methods + + private void checkAllowedValue(Object value) throws MessageFormatException + { + if (((value instanceof Boolean) || (value instanceof Byte) + || (value instanceof Short) || (value instanceof Integer) + || (value instanceof Long) || (value instanceof Character) + || (value instanceof Float) || (value instanceof Double) + || (value instanceof String) || (value instanceof byte[]) + || (value instanceof List) || (value instanceof Map) + || (value instanceof UUID) || (value == null)) == false) + { + throw new MessageFormatException("Invalid value " + value + + "of type " + value.getClass().getName() + "."); + } + } + + @Override + public void reset() + { + currentIndex = 0; + setReadable(true); + } + + @Override + public void clearBody() throws JMSException + { + super.clearBody(); + _list.clear(); + currentIndex = 0; + setReadable(false); + } + + private boolean getBooleanImpl(int index) throws JMSException + { + Object value = get(index); + + if (value instanceof Boolean) + { + return ((Boolean) value).booleanValue(); + } + else if ((value instanceof String) || (value == null)) + { + try + { + return Boolean.valueOf((String) value); + } + catch (NumberFormatException e) + { + // FALLTHROUGH to exception + } + } + + throw new MessageFormatException("Property at " + index + " of type " + + value.getClass().getName() + + " cannot be converted to boolean."); + } + + private byte getByteImpl(int index) throws JMSException + { + Object value = get(index); + + if (value instanceof Byte) + { + return ((Byte) value).byteValue(); + } + else if ((value instanceof String) || (value == null)) + { + try + { + return Byte.valueOf((String) value).byteValue(); + } catch (NumberFormatException e) + { + // FALLTHROUGH to exception + } + } + + throw new MessageFormatException("Property at " + index + " of type " + + value.getClass().getName() + " cannot be converted to byte."); + } + + private short getShortImpl(int index) throws JMSException + { + Object value = get(index); + + if (value instanceof Short) + { + return ((Short) value).shortValue(); + } + else if (value instanceof Byte) + { + return ((Byte) value).shortValue(); + } + else if ((value instanceof String) || (value == null)) + { + try + { + return Short.valueOf((String) value).shortValue(); + } catch (NumberFormatException e) + { + // FALLTHROUGH to exception + } + } + + throw new MessageFormatException("Property at " + index + " of type " + + value.getClass().getName() + " cannot be converted to short."); + } + + private int getIntImpl(int index) throws JMSException + { + Object value = get(index); + + if (value instanceof Integer) + { + return ((Integer) value).intValue(); + } + + if (value instanceof Short) + { + return ((Short) value).intValue(); + } + + if (value instanceof Byte) + { + return ((Byte) value).intValue(); + } + + if ((value instanceof String) || (value == null)) + { + try + { + return Integer.valueOf((String) value).intValue(); + } + catch (NumberFormatException e) + { + // FALLTHROUGH to exception + } + } + + throw new MessageFormatException("Property at " + index + " of type " + + value.getClass().getName() + " cannot be converted to int."); + } + + private long getLongImpl(int index) throws JMSException + { + Object value = get(index); + + if (value instanceof Long) + { + return ((Long) value).longValue(); + } else if (value instanceof Integer) + { + return ((Integer) value).longValue(); + } + + if (value instanceof Short) + { + return ((Short) value).longValue(); + } + + if (value instanceof Byte) + { + return ((Byte) value).longValue(); + } else if ((value instanceof String) || (value == null)) + { + try + { + return Long.valueOf((String) value).longValue(); + } catch (NumberFormatException e) + { + // FALLTHROUGH to exception + } + } + + throw new MessageFormatException("Property at " + index + " of type " + + value.getClass().getName() + " cannot be converted to long."); + } + + private char getCharImpl(int index) throws JMSException + { + Object value = get(index); + + if (value instanceof Character) + { + return ((Character) value).charValue(); + } else if (value == null) + { + throw new NullPointerException("Property at " + index + + " has null value and therefore cannot " + + "be converted to char."); + } else + { + throw new MessageFormatException("Property at " + index + + " of type " + value.getClass().getName() + + " cannot be converted to a char."); + } + } + + private float getFloatImpl(int index) throws JMSException + { + Object value = get(index); + + if (value instanceof Float) + { + return ((Float) value).floatValue(); + } + else if ((value instanceof String) || (value == null)) + { + try + { + return Float.valueOf((String) value).floatValue(); + } + catch (NumberFormatException e) + { + // FALLTHROUGH to exception + } + } + + throw new MessageFormatException("Property at " + index + " of type " + + value.getClass().getName() + " cannot be converted to float."); + } + + private double getDoubleImpl(int index) throws JMSException + { + Object value = get(index); + + if (value instanceof Double) + { + return ((Double) value).doubleValue(); + } + else if (value instanceof Float) + { + return ((Float) value).doubleValue(); + } + else if ((value instanceof String) || (value == null)) + { + try + { + return Double.valueOf((String) value).doubleValue(); + } + catch (NumberFormatException e) + { + // FALLTHROUGH to exception + } + } + + throw new MessageFormatException("Property at " + index + " of type " + + value.getClass().getName() + + " cannot be converted to double."); + } + + private String getStringImpl(int index) throws JMSException + { + Object value = get(index); + + if ((value instanceof String) || (value == null)) + { + return (String) value; + } else if (value instanceof byte[]) + { + throw new MessageFormatException("Property at " + index + + " of type byte[] " + "cannot be converted to String."); + } else + { + return value.toString(); + } + } + + private byte[] getBytesImpl(int index) throws JMSException + { + Object value = get(index); + + if ((value instanceof byte[]) || (value == null)) + { + return (byte[]) value; + } + else + { + throw new MessageFormatException("Property at " + index + + " of type " + value.getClass().getName() + + " cannot be converted to byte[]."); + } + } + + protected void populateListFromData(ByteBuffer data) throws JMSException + { + if (data != null) + { + data.rewind(); + BBDecoder decoder = new BBDecoder(); + decoder.init(data); + _list = decoder.readList(); + } + else + { + _list.clear(); + } + } + + public ByteBuffer getData() throws JMSException + { + BBEncoder encoder = new BBEncoder(1024); + encoder.writeList(_list); + return encoder.segment(); + } + + public void setList(List l) + { + _list = l; + } + + public List asList() + { + return _list; + } +} diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedListMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedListMessageFactory.java new file mode 100644 index 0000000000..b503dccb91 --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/client/message/AMQPEncodedListMessageFactory.java @@ -0,0 +1,44 @@ +package org.apache.qpid.client.message; +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + + +import org.apache.qpid.AMQException; + +import javax.jms.JMSException; +import java.nio.ByteBuffer; + +public class AMQPEncodedListMessageFactory extends AbstractJMSMessageFactory +{ + @Override + protected AbstractJMSMessage createMessage(AMQMessageDelegate delegate, + ByteBuffer data) throws AMQException + { + return new AMQPEncodedListMessage(delegate,data); + } + + + public AbstractJMSMessage createMessage( + AMQMessageDelegateFactory delegateFactory) throws JMSException + { + return new AMQPEncodedListMessage(delegateFactory); + } +} diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java index 509fc9f7f1..c2a919c1c5 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java @@ -196,7 +196,14 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag if (data != null && data.hasRemaining()) { ClassLoadingAwareObjectInputStream in = new ClassLoadingAwareObjectInputStream(new ByteBufferInputStream(data)); - result = (Serializable) in.readObject(); + try + { + result = (Serializable) in.readObject(); + } + finally + { + in.close(); + } } return result; } diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java index b958d89515..b1af262580 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java @@ -44,7 +44,12 @@ public class JMSStreamMessage extends AbstractBytesTypedMessage implements Strea } + JMSStreamMessage(AMQMessageDelegateFactory delegateFactory, ByteBuffer data) throws AMQException + { + super(delegateFactory, data!=null); + _typedBytesContentWriter = new TypedBytesContentWriter(); + } JMSStreamMessage(AMQMessageDelegate delegate, ByteBuffer data) throws AMQException { diff --git a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java index fa39b4c93c..4154003b23 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/MessageFactoryRegistry.java @@ -66,6 +66,7 @@ public class MessageFactoryRegistry mf.registerFactory(JMSObjectMessage.MIME_TYPE, new JMSObjectMessageFactory()); mf.registerFactory(JMSStreamMessage.MIME_TYPE, new JMSStreamMessageFactory()); mf.registerFactory(AMQPEncodedMapMessage.MIME_TYPE, new AMQPEncodedMapMessageFactory()); + mf.registerFactory(AMQPEncodedListMessage.MIME_TYPE, new AMQPEncodedListMessageFactory()); mf.registerFactory(null, mf._default); return mf; diff --git a/java/client/src/main/java/org/apache/qpid/client/messaging/address/AddressHelper.java b/java/client/src/main/java/org/apache/qpid/client/messaging/address/AddressHelper.java index 318fe32d36..72fc74e19c 100644 --- a/java/client/src/main/java/org/apache/qpid/client/messaging/address/AddressHelper.java +++ b/java/client/src/main/java/org/apache/qpid/client/messaging/address/AddressHelper.java @@ -20,21 +20,20 @@ */ package org.apache.qpid.client.messaging.address; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQDestination.Binding; import org.apache.qpid.client.messaging.address.Link.Reliability; import org.apache.qpid.client.messaging.address.Link.Subscription; -import org.apache.qpid.client.messaging.address.Node.ExchangeNode; -import org.apache.qpid.client.messaging.address.Node.QueueNode; +import org.apache.qpid.client.messaging.address.Link.SubscriptionQueue; import org.apache.qpid.configuration.Accessor; import org.apache.qpid.configuration.Accessor.MapAccessor; import org.apache.qpid.messaging.Address; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - /** * Utility class for extracting information from the address class */ @@ -68,58 +67,56 @@ public class AddressHelper public static final String ARGUMENTS = "arguments"; public static final String RELIABILITY = "reliability"; - private Address address; - private Accessor addressProps; - private Accessor nodeProps; - private Accessor linkProps; + private Address _address; + private Accessor _addressPropAccess; + private Accessor _nodePropAccess; + private Accessor _linkPropAccess; + private Map _addressPropMap; + private Map _nodePropMap; + private Map _linkPropMap; public AddressHelper(Address address) { - this.address = address; - addressProps = new MapAccessor(address.getOptions()); - Map node_props = address.getOptions() == null + this._address = address; + this._addressPropMap = address.getOptions(); + this._addressPropAccess = new MapAccessor(_addressPropMap); + this._nodePropMap = address.getOptions() == null || address.getOptions().get(NODE) == null ? null : (Map) address.getOptions().get(NODE); - if (node_props != null) + if (_nodePropMap != null) { - nodeProps = new MapAccessor(node_props); + _nodePropAccess = new MapAccessor(_nodePropMap); } - Map link_props = address.getOptions() == null + this._linkPropMap = address.getOptions() == null || address.getOptions().get(LINK) == null ? null : (Map) address.getOptions().get(LINK); - if (link_props != null) + if (_linkPropMap != null) { - linkProps = new MapAccessor(link_props); + _linkPropAccess = new MapAccessor(_linkPropMap); } } public String getCreate() { - return addressProps.getString(CREATE); + return _addressPropAccess.getString(CREATE); } public String getAssert() { - return addressProps.getString(ASSERT); + return _addressPropAccess.getString(ASSERT); } public String getDelete() { - return addressProps.getString(DELETE); - } - - public boolean isNoLocal() - { - Boolean b = nodeProps.getBoolean(NO_LOCAL); - return b == null ? false : b; + return _addressPropAccess.getString(DELETE); } public boolean isBrowseOnly() { - String mode = addressProps.getString(MODE); + String mode = _addressPropAccess.getString(MODE); return mode != null && mode.equals(BROWSE) ? true : false; } @@ -127,7 +124,7 @@ public class AddressHelper public List getBindings(Map props) { List bindings = new ArrayList(); - List bindingList = (List) props.get(X_BINDINGS); + List bindingList = (props == null) ? Collections.EMPTY_LIST : (List) props.get(X_BINDINGS); if (bindingList != null) { for (Map bindingMap : bindingList) @@ -157,117 +154,70 @@ public class AddressHelper } } - public int getTargetNodeType() throws Exception + public int getNodeType() throws Exception { - if (nodeProps == null || nodeProps.getString(TYPE) == null) + if (_nodePropAccess == null || _nodePropAccess.getString(TYPE) == null) { // need to query and figure out return AMQDestination.UNKNOWN_TYPE; - } else if (nodeProps.getString(TYPE).equals("queue")) + } + else if (_nodePropAccess.getString(TYPE).equals("queue")) { return AMQDestination.QUEUE_TYPE; - } else if (nodeProps.getString(TYPE).equals("topic")) + } + else if (_nodePropAccess.getString(TYPE).equals("topic")) { return AMQDestination.TOPIC_TYPE; - } else + } + else { throw new Exception("unkown exchange type"); } } - public Node getTargetNode(int addressType) + public Node getNode() { - // target node here is the default exchange - if (nodeProps == null || addressType == AMQDestination.QUEUE_TYPE) - { - return new ExchangeNode(); - } else if (addressType == AMQDestination.TOPIC_TYPE) - { - Map node = (Map) address.getOptions().get(NODE); - return createExchangeNode(node); - } else + Node node = new Node(_address.getName()); + if (_nodePropAccess != null) { - // don't know yet - return null; - } - } - - private Node createExchangeNode(Map parent) - { - Map declareArgs = getDeclareArgs(parent); - MapAccessor argsMap = new MapAccessor(declareArgs); - ExchangeNode node = new ExchangeNode(); - node.setExchangeType(argsMap.getString(TYPE) == null ? null : argsMap - .getString(TYPE)); - fillInCommonNodeArgs(node, parent, argsMap); - return node; - } + Map xDeclareMap = getDeclareArgs(_nodePropMap); + MapAccessor xDeclareMapAccessor = new MapAccessor(xDeclareMap); - private Node createQueueNode(Map parent) - { - Map declareArgs = getDeclareArgs(parent); - MapAccessor argsMap = new MapAccessor(declareArgs); - QueueNode node = new QueueNode(); - node.setAlternateExchange(argsMap.getString(ALT_EXCHANGE)); - node.setExclusive(argsMap.getBoolean(EXCLUSIVE) == null ? false - : argsMap.getBoolean(EXCLUSIVE)); - fillInCommonNodeArgs(node, parent, argsMap); - - return node; - } - - private void fillInCommonNodeArgs(Node node, Map parent, MapAccessor argsMap) - { - node.setDurable(getDurability(parent)); - node.setAutoDelete(argsMap.getBoolean(AUTO_DELETE) == null ? false - : argsMap.getBoolean(AUTO_DELETE)); - node.setAlternateExchange(argsMap.getString(ALT_EXCHANGE)); - node.setBindings(getBindings(parent)); - if (getDeclareArgs(parent).containsKey(ARGUMENTS)) - { - node.setDeclareArgs((Map)getDeclareArgs(parent).get(ARGUMENTS)); + node.setDurable(getBooleanProperty(_nodePropAccess,DURABLE,false)); + node.setAutoDelete(getBooleanProperty(xDeclareMapAccessor,AUTO_DELETE,false)); + node.setExclusive(getBooleanProperty(xDeclareMapAccessor,EXCLUSIVE,false)); + node.setAlternateExchange(xDeclareMapAccessor.getString(ALT_EXCHANGE)); + if (xDeclareMapAccessor.getString(TYPE) != null) + { + node.setExchangeType(xDeclareMapAccessor.getString(TYPE)); + } + node.setBindings(getBindings(_nodePropMap)); + if (!xDeclareMap.isEmpty() && xDeclareMap.containsKey(ARGUMENTS)) + { + node.setDeclareArgs((Map)xDeclareMap.get(ARGUMENTS)); + } } - } - - private boolean getDurability(Map map) - { - Accessor access = new MapAccessor(map); - Boolean result = access.getBoolean(DURABLE); - return (result == null) ? false : result.booleanValue(); + return node; } - /** - * if the type == queue x-declare args from the node props is used. if the - * type == exchange x-declare args from the link props is used else just - * create a default temp queue. - */ - public Node getSourceNode(int addressType) + // This should really be in the Accessor interface + private boolean getBooleanProperty(Accessor access, String propName, boolean defaultValue) { - if (addressType == AMQDestination.QUEUE_TYPE && nodeProps != null) - { - return createQueueNode((Map) address.getOptions().get(NODE)); - } - if (addressType == AMQDestination.TOPIC_TYPE && linkProps != null) - { - return createQueueNode((Map) address.getOptions().get(LINK)); - } else - { - // need to query the info - return new QueueNode(); - } + Boolean result = access.getBoolean(propName); + return (result == null) ? defaultValue : result.booleanValue(); } public Link getLink() throws Exception { Link link = new Link(); link.setSubscription(new Subscription()); - if (linkProps != null) + link.setSubscriptionQueue(new SubscriptionQueue()); + if (_linkPropAccess != null) { - link.setDurable(linkProps.getBoolean(DURABLE) == null ? false - : linkProps.getBoolean(DURABLE)); - link.setName(linkProps.getString(NAME)); + link.setDurable(getBooleanProperty(_linkPropAccess,DURABLE,false)); + link.setName(_linkPropAccess.getString(NAME)); - String reliability = linkProps.getString(RELIABILITY); + String reliability = _linkPropAccess.getString(RELIABILITY); if ( reliability != null) { if (reliability.equalsIgnoreCase("unreliable")) @@ -283,13 +233,12 @@ public class AddressHelper throw new Exception("The reliability mode '" + reliability + "' is not yet supported"); } - } - if (((Map) address.getOptions().get(LINK)).get(CAPACITY) instanceof Map) + if (((Map) _address.getOptions().get(LINK)).get(CAPACITY) instanceof Map) { MapAccessor capacityProps = new MapAccessor( - (Map) ((Map) address.getOptions().get(LINK)) + (Map) ((Map) _address.getOptions().get(LINK)) .get(CAPACITY)); link .setConsumerCapacity(capacityProps @@ -302,17 +251,19 @@ public class AddressHelper } else { - int cap = linkProps.getInt(CAPACITY) == null ? 0 : linkProps + int cap = _linkPropAccess.getInt(CAPACITY) == null ? 0 : _linkPropAccess .getInt(CAPACITY); link.setConsumerCapacity(cap); link.setProducerCapacity(cap); } - link.setFilter(linkProps.getString(FILTER)); + link.setFilter(_linkPropAccess.getString(FILTER)); // so far filter type not used - if (((Map) address.getOptions().get(LINK)).containsKey(X_SUBSCRIBE)) + Map linkMap = (Map) _address.getOptions().get(LINK); + + if (linkMap != null && linkMap.containsKey(X_SUBSCRIBE)) { - Map x_subscribe = (Map)((Map) address.getOptions().get(LINK)).get(X_SUBSCRIBE); + Map x_subscribe = (Map)((Map) _address.getOptions().get(LINK)).get(X_SUBSCRIBE); if (x_subscribe.containsKey(ARGUMENTS)) { @@ -324,6 +275,18 @@ public class AddressHelper link.getSubscription().setExclusive(exclusive); } + + link.setBindings(getBindings(linkMap)); + Map xDeclareMap = getDeclareArgs(linkMap); + SubscriptionQueue queue = link.getSubscriptionQueue(); + if (!xDeclareMap.isEmpty() && xDeclareMap.containsKey(ARGUMENTS)) + { + MapAccessor xDeclareMapAccessor = new MapAccessor(xDeclareMap); + queue.setAutoDelete(getBooleanProperty(xDeclareMapAccessor,AUTO_DELETE,true)); + queue.setExclusive(getBooleanProperty(xDeclareMapAccessor,EXCLUSIVE,true)); + queue.setAlternateExchange(xDeclareMapAccessor.getString(ALT_EXCHANGE)); + queue.setDeclareArgs((Map)xDeclareMap.get(ARGUMENTS)); + } } return link; diff --git a/java/client/src/main/java/org/apache/qpid/client/messaging/address/Link.java b/java/client/src/main/java/org/apache/qpid/client/messaging/address/Link.java index 41f6725c8f..40a84ebd02 100644 --- a/java/client/src/main/java/org/apache/qpid/client/messaging/address/Link.java +++ b/java/client/src/main/java/org/apache/qpid/client/messaging/address/Link.java @@ -20,9 +20,14 @@ */ package org.apache.qpid.client.messaging.address; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; +import org.apache.qpid.client.AMQDestination.Binding; + public class Link { public enum FilterType { SQL92, XQUERY, SUBJECT } @@ -36,10 +41,11 @@ public class Link private boolean _isDurable; private int _consumerCapacity = 0; private int _producerCapacity = 0; - private Node node; private Subscription subscription; private Reliability reliability = Reliability.AT_LEAST_ONCE; - + private List _bindings = new ArrayList(); + private SubscriptionQueue _subscriptionQueue; + public Reliability getReliability() { return reliability; @@ -50,21 +56,11 @@ public class Link this.reliability = reliability; } - public Node getNode() - { - return node; - } - - public void setNode(Node node) - { - this.node = node; - } - public boolean isDurable() { return _isDurable; } - + public void setDurable(boolean durable) { _isDurable = durable; @@ -139,6 +135,74 @@ public class Link { this.subscription = subscription; } + + public List getBindings() + { + return _bindings; + } + + public void setBindings(List bindings) + { + _bindings = bindings; + } + + public SubscriptionQueue getSubscriptionQueue() + { + return _subscriptionQueue; + } + + public void setSubscriptionQueue(SubscriptionQueue subscriptionQueue) + { + this._subscriptionQueue = subscriptionQueue; + } + + public static class SubscriptionQueue + { + private Map _declareArgs = new HashMap(); + private boolean _isAutoDelete = true; + private boolean _isExclusive = true; + private String _alternateExchange; + + public Map getDeclareArgs() + { + return _declareArgs; + } + + public void setDeclareArgs(Map options) + { + _declareArgs = options; + } + + public boolean isAutoDelete() + { + return _isAutoDelete; + } + + public void setAutoDelete(boolean autoDelete) + { + _isAutoDelete = autoDelete; + } + + public boolean isExclusive() + { + return _isExclusive; + } + + public void setExclusive(boolean exclusive) + { + _isExclusive = exclusive; + } + + public String getAlternateExchange() + { + return _alternateExchange; + } + + public void setAlternateExchange(String altExchange) + { + _alternateExchange = altExchange; + } + } public static class Subscription { diff --git a/java/client/src/main/java/org/apache/qpid/client/messaging/address/Node.java b/java/client/src/main/java/org/apache/qpid/client/messaging/address/Node.java index 0da0327885..005f98f344 100644 --- a/java/client/src/main/java/org/apache/qpid/client/messaging/address/Node.java +++ b/java/client/src/main/java/org/apache/qpid/client/messaging/address/Node.java @@ -26,19 +26,33 @@ import org.apache.qpid.client.AMQDestination.Binding; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; -public abstract class Node +public class Node { private int _nodeType = AMQDestination.UNKNOWN_TYPE; + private String _name; private boolean _isDurable; private boolean _isAutoDelete; + private boolean _isExclusive; private String _alternateExchange; + private String _exchangeType = "topic"; // used when node is an exchange instead of a queue. private List _bindings = new ArrayList(); - private Map _declareArgs = Collections.emptyMap(); + private Map _declareArgs = new HashMap(); - protected Node(int nodeType) + protected Node(String name) + { + _name = name; + } + + public String getName() + { + return _name; + } + + public void setNodeType(int nodeType) { _nodeType = nodeType; } @@ -58,6 +72,16 @@ public abstract class Node _isDurable = durable; } + public boolean isExclusive() + { + return _isExclusive; + } + + public void setExclusive(boolean exclusive) + { + _isExclusive = exclusive; + } + public boolean isAutoDelete() { return _isAutoDelete; @@ -100,56 +124,15 @@ public abstract class Node public void setDeclareArgs(Map options) { _declareArgs = options; - } - - public static class QueueNode extends Node - { - private boolean _isExclusive; - private QpidQueueOptions _queueOptions = new QpidQueueOptions(); - - public QueueNode() - { - super(AMQDestination.QUEUE_TYPE); - } - - public boolean isExclusive() - { - return _isExclusive; - } - - public void setExclusive(boolean exclusive) - { - _isExclusive = exclusive; - } } - - public static class ExchangeNode extends Node - { - private QpidExchangeOptions _exchangeOptions = new QpidExchangeOptions(); - private String _exchangeType; - - public ExchangeNode() - { - super(AMQDestination.TOPIC_TYPE); - } - - public String getExchangeType() - { - return _exchangeType; - } - - public void setExchangeType(String exchangeType) - { - _exchangeType = exchangeType; - } - + + public void setExchangeType(String type) + { + _exchangeType = type; } - - public static class UnknownNodeType extends Node + + public String getExchangeType() { - public UnknownNodeType() - { - super(AMQDestination.UNKNOWN_TYPE); - } + return _exchangeType; } } diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index b314453e31..816caac824 100644 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.client.protocol; +import org.apache.qpid.client.HeartbeatListener; import org.apache.qpid.util.BytesDataOutput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,6 +57,7 @@ import org.apache.qpid.protocol.AMQMethodListener; import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.thread.Threading; import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.network.NetworkConnection; import java.io.IOException; @@ -177,6 +179,9 @@ public class AMQProtocolHandler implements ProtocolEngine private NetworkConnection _network; private Sender _sender; + private long _lastReadTime = System.currentTimeMillis(); + private long _lastWriteTime = System.currentTimeMillis(); + private HeartbeatListener _heartbeatListener = HeartbeatListener.DEFAULT; /** * Creates a new protocol handler, associated with the specified client connection instance. @@ -210,48 +215,67 @@ public class AMQProtocolHandler implements ProtocolEngine } else { - _logger.debug("Session closed called with failover state currently " + _failoverState); - - // reconnetablility was introduced here so as not to disturb the client as they have made their intentions - // known through the policy settings. - - if ((_failoverState != FailoverState.IN_PROGRESS) && _connection.failoverAllowed()) + // Use local variable to keep flag whether fail-over allowed or not, + // in order to execute AMQConnection#exceptionRecievedout out of synchronization block, + // otherwise it might deadlock with failover mutex + boolean failoverNotAllowed = false; + synchronized (this) { - _logger.debug("FAILOVER STARTING"); - if (_failoverState == FailoverState.NOT_STARTED) - { - _failoverState = FailoverState.IN_PROGRESS; - startFailoverThread(); - } - else - { - _logger.debug("Not starting failover as state currently " + _failoverState); - } - } - else - { - _logger.debug("Failover not allowed by policy."); // or already in progress? - if (_logger.isDebugEnabled()) { - _logger.debug(_connection.getFailoverPolicy().toString()); + _logger.debug("Session closed called with failover state " + _failoverState); } - if (_failoverState != FailoverState.IN_PROGRESS) + // reconnetablility was introduced here so as not to disturb the client as they have made their intentions + // known through the policy settings. + if (_failoverState == FailoverState.NOT_STARTED) { - _logger.debug("sessionClose() not allowed to failover"); - _connection.exceptionReceived(new AMQDisconnectedException( - "Server closed connection and reconnection " + "not permitted.", - _stateManager.getLastException())); + // close the sender + try + { + _sender.close(); + } + catch (Exception e) + { + _logger.warn("Exception occured on closing the sender", e); + } + if (_connection.failoverAllowed()) + { + _failoverState = FailoverState.IN_PROGRESS; + + _logger.debug("FAILOVER STARTING"); + startFailoverThread(); + } + else if (_connection.isConnected()) + { + failoverNotAllowed = true; + if (_logger.isDebugEnabled()) + { + _logger.debug("Failover not allowed by policy:" + _connection.getFailoverPolicy()); + } + } + else + { + _logger.debug("We are in process of establishing the initial connection"); + } } else { - _logger.debug("sessionClose() failover in progress"); + _logger.debug("Not starting the failover thread as state currently " + _failoverState); } } + + if (failoverNotAllowed) + { + _connection.exceptionReceived(new AMQDisconnectedException( + "Server closed connection and reconnection not permitted.", _stateManager.getLastException())); + } } - _logger.debug("Protocol Session [" + this + "] closed"); + if (_logger.isDebugEnabled()) + { + _logger.debug("Protocol Session [" + this + "] closed"); + } } /** See {@link FailoverHandler} to see rationale for separate thread. */ @@ -280,7 +304,6 @@ public class AMQProtocolHandler implements ProtocolEngine { _logger.debug("Protocol Session [" + this + "] idle: reader"); // failover: - HeartbeatDiagnostics.timeout(); _logger.warn("Timed out while waiting for heartbeat from peer."); _network.close(); } @@ -289,7 +312,7 @@ public class AMQProtocolHandler implements ProtocolEngine { _logger.debug("Protocol Session [" + this + "] idle: reader"); writeFrame(HeartbeatBody.FRAME); - HeartbeatDiagnostics.sent(); + _heartbeatListener.heartbeatSent(); } /** @@ -297,14 +320,29 @@ public class AMQProtocolHandler implements ProtocolEngine */ public void exception(Throwable cause) { - if (_failoverState == FailoverState.NOT_STARTED) + boolean causeIsAConnectionProblem = + cause instanceof AMQConnectionClosedException || + cause instanceof IOException || + cause instanceof TransportException; + + if (causeIsAConnectionProblem) { - if ((cause instanceof AMQConnectionClosedException) || cause instanceof IOException) + //ensure the IoSender and IoReceiver are closed + try { - _logger.info("Exception caught therefore going to attempt failover: " + cause, cause); - // this will attempt failover _network.close(); - closed(); + } + catch (Exception e) + { + //ignore + } + } + FailoverState state = getFailoverState(); + if (state == FailoverState.NOT_STARTED) + { + if (causeIsAConnectionProblem) + { + _logger.info("Connection exception caught therefore going to attempt failover: " + cause, cause); } else { @@ -319,7 +357,7 @@ public class AMQProtocolHandler implements ProtocolEngine } // 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 - else if (_failoverState == FailoverState.FAILED) + else if (state == FailoverState.FAILED) { _logger.error("Exception caught by protocol handler: " + cause, cause); @@ -329,6 +367,10 @@ public class AMQProtocolHandler implements ProtocolEngine propagateExceptionToAllWaiters(amqe); _connection.exceptionReceived(cause); } + else + { + _logger.warn("Exception caught by protocol handler: " + cause, cause); + } } /** @@ -403,6 +445,7 @@ public class AMQProtocolHandler implements ProtocolEngine public void received(ByteBuffer msg) { _readBytes += msg.remaining(); + _lastReadTime = System.currentTimeMillis(); try { final ArrayList dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); @@ -431,8 +474,6 @@ public class AMQProtocolHandler implements ProtocolEngine final AMQBody bodyFrame = frame.getBodyFrame(); - HeartbeatDiagnostics.received(bodyFrame instanceof HeartbeatBody); - bodyFrame.handle(frame.getChannel(), _protocolSession); _connection.bytesReceived(_readBytes); @@ -521,6 +562,7 @@ public class AMQProtocolHandler implements ProtocolEngine public synchronized void writeFrame(AMQDataBlock frame, boolean flush) { final ByteBuffer buf = asByteBuffer(frame); + _lastWriteTime = System.currentTimeMillis(); _writtenBytes += buf.remaining(); _sender.send(buf); if(flush) @@ -792,14 +834,14 @@ public class AMQProtocolHandler implements ProtocolEngine return _protocolSession; } - FailoverState getFailoverState() + synchronized FailoverState getFailoverState() { return _failoverState; } - public void setFailoverState(FailoverState failoverState) + public synchronized void setFailoverState(FailoverState failoverState) { - _failoverState = failoverState; + _failoverState= failoverState; } public byte getProtocolMajorVersion() @@ -843,6 +885,23 @@ public class AMQProtocolHandler implements ProtocolEngine _sender = sender; } + @Override + public long getLastReadTime() + { + return _lastReadTime; + } + + @Override + public long getLastWriteTime() + { + return _lastWriteTime; + } + + protected Sender getSender() + { + return _sender; + } + /** @param delay delay in seconds (not ms) */ void initHeartbeats(int delay) { @@ -850,7 +909,6 @@ public class AMQProtocolHandler implements ProtocolEngine { _network.setMaxWriteIdle(delay); _network.setMaxReadIdle(HeartbeatConfig.CONFIG.getTimeout(delay)); - HeartbeatDiagnostics.init(delay, HeartbeatConfig.CONFIG.getTimeout(delay)); } } @@ -865,5 +923,13 @@ public class AMQProtocolHandler implements ProtocolEngine } + public void setHeartbeatListener(HeartbeatListener listener) + { + _heartbeatListener = listener == null ? HeartbeatListener.DEFAULT : listener; + } + public void heartbeatBodyReceived() + { + _heartbeatListener.heartbeatReceived(); + } } diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java index af57fd98fc..aed10cf15f 100644 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java +++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java @@ -48,6 +48,8 @@ import org.apache.qpid.transport.TransportException; import javax.jms.JMSException; import javax.security.sasl.SaslClient; + +import java.nio.ByteBuffer; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -265,7 +267,7 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession public void heartbeatBodyReceived(int channelId, HeartbeatBody body) throws AMQException { - + _protocolHandler.heartbeatBodyReceived(); } /** @@ -372,6 +374,11 @@ public class AMQProtocolSession implements AMQVersionAwareProtocolSession } } + public Sender getSender() + { + return _protocolHandler.getSender(); + } + public void failover(String host, int port) { _protocolHandler.failover(host, port); diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/HeartbeatDiagnostics.java b/java/client/src/main/java/org/apache/qpid/client/protocol/HeartbeatDiagnostics.java deleted file mode 100644 index d387a8ba93..0000000000 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/HeartbeatDiagnostics.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.client.protocol; - -class HeartbeatDiagnostics -{ - private static final Diagnostics _impl = init(); - - private HeartbeatDiagnostics() - { - } - - private static Diagnostics init() - { - return Boolean.getBoolean("amqj.heartbeat.diagnostics") ? new On() : new Off(); - } - - static void sent() - { - _impl.sent(); - } - - static void timeout() - { - _impl.timeout(); - } - - static void received(boolean heartbeat) - { - _impl.received(heartbeat); - } - - static void init(int delay, int timeout) - { - _impl.init(delay, timeout); - } - - private static interface Diagnostics - { - void sent(); - void timeout(); - void received(boolean heartbeat); - void init(int delay, int timeout); - } - - private static class On implements Diagnostics - { - private final String[] messages = new String[50]; - private int i; - - private void save(String msg) - { - messages[i++] = msg; - if(i >= messages.length){ - i = 0;//i.e. a circular buffer - } - } - - public void sent() - { - save(System.currentTimeMillis() + ": sent heartbeat"); - } - - public void timeout() - { - for(int i = 0; i < messages.length; i++) - { - if(messages[i] != null) - { - System.out.println(messages[i]); - } - } - System.out.println(System.currentTimeMillis() + ": timed out"); - } - - public void received(boolean heartbeat) - { - save(System.currentTimeMillis() + ": received " + (heartbeat ? "heartbeat" : "data")); - } - - public void init(int delay, int timeout) - { - System.out.println(System.currentTimeMillis() + ": initialised delay=" + delay + ", timeout=" + timeout); - } - } - - private static class Off implements Diagnostics - { - public void sent() - { - - } - public void timeout() - { - - } - public void received(boolean heartbeat) - { - - } - - public void init(int delay, int timeout) - { - - } - } -} diff --git a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java index 9198903408..b43229292f 100644 --- a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java +++ b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java @@ -28,8 +28,10 @@ import org.apache.qpid.util.FileUtils; import javax.security.sasl.SaslClientFactory; import java.io.IOException; import java.io.InputStream; +import java.security.Provider; import java.security.Security; import java.util.Enumeration; +import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.TreeMap; @@ -67,10 +69,10 @@ public class DynamicSaslRegistrar } /** Reads the properties file, and creates a dynamic security provider to register the SASL implementations with. */ - public static void registerSaslProviders() + public static ProviderRegistrationResult registerSaslProviders() { _logger.debug("public static void registerSaslProviders(): called"); - + ProviderRegistrationResult result = ProviderRegistrationResult.FAILED; // Open the SASL properties file, using the default name is one is not specified. String filename = System.getProperty(FILE_PROPERTY); InputStream is = @@ -89,22 +91,45 @@ public class DynamicSaslRegistrar if (factories.size() > 0) { // Ensure we are used before the defaults - if (Security.insertProviderAt(new JCAProvider(factories), 1) == -1) + JCAProvider qpidProvider = new JCAProvider(factories); + if (Security.insertProviderAt(qpidProvider, 1) == -1) { - _logger.error("Unable to load custom SASL providers."); + Provider registeredProvider = findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME); + if (registeredProvider == null) + { + result = ProviderRegistrationResult.FAILED; + _logger.error("Unable to load custom SASL providers."); + } + else if (registeredProvider.equals(qpidProvider)) + { + result = ProviderRegistrationResult.EQUAL_ALREADY_REGISTERED; + _logger.debug("Custom SASL provider is already registered with equal properties."); + } + else + { + result = ProviderRegistrationResult.DIFFERENT_ALREADY_REGISTERED; + _logger.warn("Custom SASL provider was already registered with different properties."); + if (_logger.isDebugEnabled()) + { + _logger.debug("Custom SASL provider " + registeredProvider + " properties: " + new HashMap(registeredProvider)); + } + } } else { + result = ProviderRegistrationResult.SUCCEEDED; _logger.info("Additional SASL providers successfully registered."); } } else { - _logger.warn("No additional SASL providers registered."); + result = ProviderRegistrationResult.NO_SASL_FACTORIES; + _logger.warn("No additional SASL factories found to register."); } } catch (IOException e) { + result = ProviderRegistrationResult.FAILED; _logger.error("Error reading properties: " + e, e); } finally @@ -122,6 +147,22 @@ public class DynamicSaslRegistrar } } } + return result; + } + + static Provider findProvider(String name) + { + Provider[] providers = Security.getProviders(); + Provider registeredProvider = null; + for (Provider provider : providers) + { + if (name.equals(provider.getName())) + { + registeredProvider = provider; + break; + } + } + return registeredProvider; } /** @@ -158,15 +199,24 @@ public class DynamicSaslRegistrar continue; } - _logger.debug("Registering class "+ clazz.getName() +" for mechanism "+mechanism); + _logger.debug("Found class "+ clazz.getName() +" for mechanism "+mechanism); factoriesToRegister.put(mechanism, (Class) clazz); } catch (Exception ex) { - _logger.error("Error instantiating SaslClientFactory calss " + className + " - skipping"); + _logger.error("Error instantiating SaslClientFactory class " + className + " - skipping"); } } return factoriesToRegister; } + + public static enum ProviderRegistrationResult + { + SUCCEEDED, + EQUAL_ALREADY_REGISTERED, + DIFFERENT_ALREADY_REGISTERED, + NO_SASL_FACTORIES, + FAILED; + } } diff --git a/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java b/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java index 4a91f805f6..c9bcaf0d15 100644 --- a/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java +++ b/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java @@ -39,6 +39,11 @@ import java.util.Map; */ public class JCAProvider extends Provider { + static final String QPID_CLIENT_SASL_PROVIDER_NAME = "AMQSASLProvider-Client"; + static final String QPID_CLIENT_SASL_PROVIDER_INFO = "A JCA provider that registers all " + + "AMQ SASL providers that want to be registered"; + static final double QPID_CLIENT_SASL_PROVIDER_VERSION = 1.0; + private static final Logger log = LoggerFactory.getLogger(JCAProvider.class); /** @@ -48,8 +53,7 @@ public class JCAProvider extends Provider */ public JCAProvider(Map> providerMap) { - super("AMQSASLProvider-Client", 1.0, "A JCA provider that registers all " - + "AMQ SASL providers that want to be registered"); + super(QPID_CLIENT_SASL_PROVIDER_NAME, QPID_CLIENT_SASL_PROVIDER_VERSION, QPID_CLIENT_SASL_PROVIDER_INFO); register(providerMap); } @@ -63,7 +67,7 @@ public class JCAProvider extends Provider for (Map.Entry> me : providerMap.entrySet()) { put( "SaslClientFactory."+me.getKey(), me.getValue().getName()); - log.debug("Registered SASL Client factory for " + me.getKey() + " as " + me.getValue().getName()); + log.debug("Recording SASL Client factory for " + me.getKey() + " as " + me.getValue().getName()); } } } diff --git a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java index 0b6217ffce..ed75e1f4c3 100644 --- a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java +++ b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java @@ -157,12 +157,15 @@ public class AMQStateManager implements AMQMethodListener if (_waiters.size() == 0) { - _logger.error("No Waiters for error saving as last error:" + error.getMessage()); + _logger.info("No Waiters for error. Saving as last error:" + error.getMessage()); _lastException = error; } for (StateWaiter waiter : _waiters) { - _logger.error("Notifying Waiters(" + _waiters + ") for error:" + error.getMessage()); + if(_logger.isDebugEnabled()) + { + _logger.debug("Notifying waiter " + waiter + " for error:" + error.getMessage()); + } waiter.error(error); } } diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java b/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java index 3c9a6e1500..4789dd0ed7 100644 --- a/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java +++ b/java/client/src/main/java/org/apache/qpid/client/transport/ClientConnectionDelegate.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.client.transport; +import org.apache.qpid.client.HeartbeatListener; +import org.apache.qpid.transport.ConnectionHeartbeat; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSManager; @@ -70,6 +72,7 @@ public class ClientConnectionDelegate extends ClientDelegate } private final ConnectionURL _connectionURL; + private HeartbeatListener _heartbeatListener = HeartbeatListener.DEFAULT; /** * @param settings @@ -165,4 +168,19 @@ public class ClientConnectionDelegate extends ClientDelegate return null; } + + @Override + public void connectionHeartbeat(Connection conn, ConnectionHeartbeat hearbeat) + { + // ClientDelegate simply responds to heartbeats with heartbeats + _heartbeatListener.heartbeatReceived(); + super.connectionHeartbeat(conn, hearbeat); + _heartbeatListener.heartbeatSent(); + } + + + public void setHeartbeatListener(HeartbeatListener listener) + { + _heartbeatListener = listener == null ? HeartbeatListener.DEFAULT : listener; + } } diff --git a/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java b/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java index 8fd6ff6d33..c4fbeb5607 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java +++ b/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java @@ -20,9 +20,8 @@ */ package org.apache.qpid.jms; -import org.apache.qpid.framing.AMQShortString; - import java.util.List; +import org.apache.qpid.framing.AMQShortString; /** Connection URL format @@ -35,13 +34,21 @@ public interface ConnectionURL public static final String AMQ_PROTOCOL = "amqp"; public static final String OPTIONS_SYNC_PERSISTENCE = "sync_persistence"; public static final String OPTIONS_MAXPREFETCH = "maxprefetch"; - public static final String OPTIONS_SYNC_ACK = "sync_ack"; + public static final String OPTIONS_SYNC_ACK = "sync_ack"; public static final String OPTIONS_SYNC_PUBLISH = "sync_publish"; public static final String OPTIONS_USE_LEGACY_MAP_MESSAGE_FORMAT = "use_legacy_map_msg_format"; + public static final String OPTIONS_USE_LEGACY_STREAM_MESSAGE_FORMAT = "use_legacy_stream_msg_format"; public static final String OPTIONS_BROKERLIST = "brokerlist"; public static final String OPTIONS_FAILOVER = "failover"; public static final String OPTIONS_FAILOVER_CYCLE = "cyclecount"; + /** + * This option is used to apply a connection level override of + * the {@value BrokerDetails#OPTIONS_SSL} option values in the + * {@value ConnectionURL#OPTIONS_BROKERLIST}; + */ + public static final String OPTIONS_SSL = "ssl"; + /** * This option is only applicable for 0-8/0-9/0-9-1 protocols connection *

@@ -54,9 +61,11 @@ public interface ConnectionURL public static final String OPTIONS_DEFAULT_QUEUE_EXCHANGE = "defaultQueueExchange"; public static final String OPTIONS_TEMPORARY_TOPIC_EXCHANGE = "temporaryTopicExchange"; public static final String OPTIONS_TEMPORARY_QUEUE_EXCHANGE = "temporaryQueueExchange"; + public static final String OPTIONS_VERIFY_QUEUE_ON_SEND = "verifyQueueOnSend"; + public static final byte URL_0_8 = 1; public static final byte URL_0_10 = 2; - + String getURL(); String getFailoverMethod(); diff --git a/java/client/src/main/java/org/apache/qpid/jms/ListMessage.java b/java/client/src/main/java/org/apache/qpid/jms/ListMessage.java new file mode 100644 index 0000000000..21dd2a89ee --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/jms/ListMessage.java @@ -0,0 +1,55 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.jms; + +import javax.jms.JMSException; + +import java.util.Iterator; +import java.util.List; + +public interface ListMessage extends javax.jms.StreamMessage +{ + boolean add(Object e) throws JMSException; + + void add(int index, Object e) throws JMSException; + + boolean contains(Object e) throws JMSException; + + Object get(int index) throws JMSException; + + int indexOf(Object e) throws JMSException; + + Iterator iterator() throws JMSException; + + Object remove(int index) throws JMSException; + + boolean remove(Object e)throws JMSException; + + Object set(int index, Object e) throws JMSException; + + int size() throws JMSException; + + Object[] toArray() throws JMSException; + + List asList() throws JMSException; + + void setList(List l) throws JMSException; +} diff --git a/java/client/src/main/java/org/apache/qpid/jms/MessageProducer.java b/java/client/src/main/java/org/apache/qpid/jms/MessageProducer.java index bec8b0917d..82c2b88c30 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/MessageProducer.java +++ b/java/client/src/main/java/org/apache/qpid/jms/MessageProducer.java @@ -23,25 +23,11 @@ package org.apache.qpid.jms; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; -import java.io.UnsupportedEncodingException; /** */ public interface MessageProducer extends javax.jms.MessageProducer { - /** - * Set the default MIME type for messages produced by this producer. This reduces the overhead of each message. - * @param mimeType - */ - void setMimeType(String mimeType) throws JMSException; - - /** - * Set the default encoding for messages produced by this producer. This reduces the overhead of each message. - * @param encoding the encoding as understood by XXXX how do I specify this?? RG - * @throws UnsupportedEncodingException if the encoding is not understood - */ - void setEncoding(String encoding) throws UnsupportedEncodingException, JMSException; - void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, boolean immediate) throws JMSException; diff --git a/java/client/src/main/java/org/apache/qpid/jms/Session.java b/java/client/src/main/java/org/apache/qpid/jms/Session.java index b4bf2d1d85..4801f87295 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/Session.java +++ b/java/client/src/main/java/org/apache/qpid/jms/Session.java @@ -21,6 +21,7 @@ package org.apache.qpid.jms; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.jms.ListMessage; import javax.jms.Destination; import javax.jms.JMSException; @@ -100,4 +101,6 @@ public interface Session extends TopicSession, QueueSession AMQShortString getDefaultTopicExchangeName(); AMQShortString getTemporaryQueueExchangeName(); + + ListMessage createListMessage() throws JMSException; } diff --git a/java/client/src/test/java/org/apache/qpid/client/AMQConnectionUnitTest.java b/java/client/src/test/java/org/apache/qpid/client/AMQConnectionUnitTest.java index d186a440da..d309251b44 100644 --- a/java/client/src/test/java/org/apache/qpid/client/AMQConnectionUnitTest.java +++ b/java/client/src/test/java/org/apache/qpid/client/AMQConnectionUnitTest.java @@ -20,25 +20,60 @@ */ package org.apache.qpid.client; -import junit.framework.TestCase; - -import org.apache.qpid.AMQInvalidArgumentException; +import java.util.concurrent.atomic.AtomicReference; import javax.jms.ExceptionListener; import javax.jms.JMSException; -import java.util.concurrent.atomic.AtomicReference; -public class AMQConnectionUnitTest extends TestCase +import org.apache.qpid.AMQInvalidArgumentException; +import org.apache.qpid.configuration.ClientProperties; +import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.test.utils.QpidTestCase; + +public class AMQConnectionUnitTest extends QpidTestCase { + String _url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672'"; + + public void testVerifyQueueOnSendDefault() throws Exception + { + MockAMQConnection connection = new MockAMQConnection(_url); + assertFalse(connection.validateQueueOnSend()); + } + + public void testVerifyQueueOnSendViaSystemProperty() throws Exception + { + setTestSystemProperty(ClientProperties.VERIFY_QUEUE_ON_SEND, "true"); + MockAMQConnection connection = new MockAMQConnection(_url); + assertTrue(connection.validateQueueOnSend()); + + setTestSystemProperty(ClientProperties.VERIFY_QUEUE_ON_SEND, "false"); + connection = new MockAMQConnection(_url); + assertFalse(connection.validateQueueOnSend()); + } + + public void testVerifyQueueOnSendViaURL() throws Exception + { + MockAMQConnection connection = new MockAMQConnection(_url + "&" + ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND + "='true'"); + assertTrue(connection.validateQueueOnSend()); + + connection = new MockAMQConnection(_url + "&" + ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND + "='false'"); + assertFalse(connection.validateQueueOnSend()); + } + + public void testVerifyQueueOnSendViaURLoverridesSystemProperty() throws Exception + { + setTestSystemProperty(ClientProperties.VERIFY_QUEUE_ON_SEND, "false"); + MockAMQConnection connection = new MockAMQConnection(_url + "&" + ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND + "='true'"); + assertTrue(connection.validateQueueOnSend()); + } public void testExceptionReceived() { - String url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672'"; AMQInvalidArgumentException expectedException = new AMQInvalidArgumentException("Test", null); final AtomicReference receivedException = new AtomicReference(); try { - MockAMQConnection connection = new MockAMQConnection(url); + MockAMQConnection connection = new MockAMQConnection(_url); connection.setExceptionListener(new ExceptionListener() { @@ -62,4 +97,22 @@ public class AMQConnectionUnitTest extends TestCase assertEquals("JMSException linked exception is incorrect", expectedException, exception.getLinkedException()); } + /** + * This should expand to test all the defaults. + */ + public void testDefaultStreamMessageEncoding() throws Exception + { + MockAMQConnection connection = new MockAMQConnection(_url); + assertTrue("Legacy Stream message encoding should be the default",connection.isUseLegacyStreamMessageFormat()); + } + + /** + * This should expand to test all the connection properties. + */ + public void testStreamMessageEncodingProperty() throws Exception + { + MockAMQConnection connection = new MockAMQConnection(_url + "&use_legacy_stream_msg_format='false'"); + assertFalse("Stream message encoding should be amqp/list",connection.isUseLegacyStreamMessageFormat()); + } + } diff --git a/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java b/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java index 028e2d5cc3..40ed9319f1 100644 --- a/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java +++ b/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_10Test.java @@ -18,6 +18,7 @@ */ package org.apache.qpid.client; +import org.apache.qpid.client.message.AMQPEncodedListMessage; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.transport.*; @@ -28,6 +29,8 @@ import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.MessageProducer; +import javax.jms.StreamMessage; + import java.util.ArrayList; import java.util.List; @@ -276,7 +279,7 @@ public class AMQSession_0_10Test extends QpidTestCase { BasicMessageConsumer_0_10 consumer = session.createMessageConsumer(createDestination(), 1, 1, true, false, null, null, false, true); - session.sendConsume(consumer, new AMQShortString("test"), null, true, 1); + session.sendConsume(consumer, new AMQShortString("test"), true, 1); } catch (Exception e) { @@ -459,6 +462,13 @@ public class AMQSession_0_10Test extends QpidTestCase assertNotNull("ExchangeDeclare event was not sent", event); } + public void testCreateStreamMessage() throws Exception + { + AMQSession_0_10 session = createAMQSession_0_10(); + StreamMessage m = session.createStreamMessage(); + assertTrue("Legacy Stream message encoding should be the default" + m.getClass(),!(m instanceof AMQPEncodedListMessage)); + } + public void testGetQueueDepthWithSync() { // slow down a flush thread @@ -587,7 +597,7 @@ public class AMQSession_0_10Test extends QpidTestCase connection.setSessionFactory(new SessionFactory() { - public Session newSession(Connection conn, Binary name, long expiry) + public Session newSession(Connection conn, Binary name, long expiry, boolean isNoReplay) { return new MockSession(conn, new SessionDelegate(), name, expiry, throwException); } @@ -660,7 +670,6 @@ public class AMQSession_0_10Test extends QpidTestCase if (m instanceof ExchangeBound) { ExchangeBoundResult struc = new ExchangeBoundResult(); - struc.setQueueNotFound(true); result.setValue(struc); } else if (m instanceof ExchangeQuery) diff --git a/java/client/src/test/java/org/apache/qpid/client/BasicMessageConsumer_0_8_Test.java b/java/client/src/test/java/org/apache/qpid/client/BasicMessageConsumer_0_8_Test.java index 722cbd0752..066ece7ed1 100644 --- a/java/client/src/test/java/org/apache/qpid/client/BasicMessageConsumer_0_8_Test.java +++ b/java/client/src/test/java/org/apache/qpid/client/BasicMessageConsumer_0_8_Test.java @@ -48,7 +48,7 @@ public class BasicMessageConsumer_0_8_Test extends TestCase TestAMQSession testSession = new TestAMQSession(conn); BasicMessageConsumer_0_8 consumer = - new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); + new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); assertEquals("Reject behaviour was was not as expected", RejectBehaviour.SERVER, consumer.getRejectBehaviour()); } @@ -68,7 +68,7 @@ public class BasicMessageConsumer_0_8_Test extends TestCase final TestAMQSession testSession = new TestAMQSession(conn); final BasicMessageConsumer_0_8 consumer = - new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); + new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); assertEquals("Reject behaviour was was not as expected", RejectBehaviour.NORMAL, consumer.getRejectBehaviour()); } @@ -94,7 +94,7 @@ public class BasicMessageConsumer_0_8_Test extends TestCase TestAMQSession testSession = new TestAMQSession(conn); BasicMessageConsumer_0_8 consumer = - new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); + new BasicMessageConsumer_0_8(0, conn, queue, "", false, null, testSession, null, 10, 5, false, Session.SESSION_TRANSACTED, false, false); assertEquals("Reject behaviour was was not as expected", RejectBehaviour.NORMAL, consumer.getRejectBehaviour()); } diff --git a/java/client/src/test/java/org/apache/qpid/client/message/AMQPEncodedListMessageUnitTest.java b/java/client/src/test/java/org/apache/qpid/client/message/AMQPEncodedListMessageUnitTest.java new file mode 100644 index 0000000000..e131ab3dd2 --- /dev/null +++ b/java/client/src/test/java/org/apache/qpid/client/message/AMQPEncodedListMessageUnitTest.java @@ -0,0 +1,153 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.client.message; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.jms.MessageFormatException; + +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.transport.codec.BBEncoder; + +public class AMQPEncodedListMessageUnitTest extends QpidTestCase +{ + + Map _map = new HashMap(); + List _list = new ArrayList(); + UUID _uuid = UUID.randomUUID(); + + @Override + public void setUp() throws Exception + { + super.setUp(); + _map.put("Key1","String1"); + _map.put("Key2","String2"); + _map.put("Key3","String3"); + + _list.add(1); + _list.add(2); + _list.add(3); + } + + /** + * Test whether we accept the correct types while rejecting invalid types. + */ + public void testAddObject() throws Exception + { + AMQPEncodedListMessage m = new AMQPEncodedListMessage(AMQMessageDelegateFactory.FACTORY_0_10); + m.add(true); + m.add((byte)256); + m.add(Short.MAX_VALUE); + m.add(Integer.MAX_VALUE); + m.add(Long.MAX_VALUE); + m.add(10.22); + m.add("Msg"); + m.add("Msg".getBytes()); + m.add(_list); + m.add(_map); + m.add(_uuid); + + try + { + m.add(new Object()); + fail("Validation for element type failed"); + } + catch (MessageFormatException e) + { + } + } + + public void testListBehaviorForIncommingMsg() throws Exception + { + BBEncoder encoder = new BBEncoder(1024); + encoder.writeList(_list); + AMQPEncodedListMessage m = new AMQPEncodedListMessage(new AMQMessageDelegate_0_10(),encoder.segment()); + + assertTrue("contains(Object) method did not return true as expected",m.contains(1)); + assertFalse("contains(Object) method did not return false as expected",m.contains(5)); + assertEquals("get(index) method returned incorrect value",((Integer)m.get(1)).intValue(),2); + assertEquals("indexOf(Object) method returned incorrect index",m.indexOf(2),1); + try + { + m.get(10); + } + catch (MessageFormatException e) + { + assertTrue("Incorrect exception type. Expected IndexOutOfBoundsException", e.getCause() instanceof IndexOutOfBoundsException); + } + } + + public void testStreamMessageInterfaceForIncommingMsg() throws Exception + { + BBEncoder encoder = new BBEncoder(1024); + encoder.writeList(getList()); + AMQPEncodedListMessage m = new AMQPEncodedListMessage(new AMQMessageDelegate_0_10(),encoder.segment()); + + assertEquals(true,m.readBoolean()); + assertEquals((byte)256,m.readByte()); + assertEquals(Short.MAX_VALUE,m.readShort()); + assertEquals(Integer.MAX_VALUE,m.readInt()); + assertEquals(Long.MAX_VALUE,m.readLong()); + assertEquals(10.22,m.readDouble()); + assertEquals("Msg",m.readString()); + assertEquals(_list,(List)m.readObject()); + assertEquals(_map,(Map)m.readObject()); + assertEquals(_uuid,(UUID)m.readObject()); + } + + public void testMapMessageInterfaceForIncommingMsg() throws Exception + { + BBEncoder encoder = new BBEncoder(1024); + encoder.writeList(getList()); + AMQPEncodedListMessage m = new AMQPEncodedListMessage(new AMQMessageDelegate_0_10(),encoder.segment()); + + assertEquals(true,m.getBoolean("0")); + assertEquals((byte)256,m.getByte("1")); + assertEquals(Short.MAX_VALUE,m.getShort("2")); + assertEquals(Integer.MAX_VALUE,m.getInt("3")); + assertEquals(Long.MAX_VALUE,m.getLong("4")); + assertEquals(10.22,m.getDouble("5")); + assertEquals("Msg",m.getString("6")); + assertEquals(_list,(List)m.getObject("7")); + assertEquals(_map,(Map)m.getObject("8")); + assertEquals(_uuid,(UUID)m.getObject("9")); + } + + public List getList() + { + List myList = new ArrayList(); + myList.add(true); + myList.add((byte)256); + myList.add(Short.MAX_VALUE); + myList.add(Integer.MAX_VALUE); + myList.add(Long.MAX_VALUE); + myList.add(10.22); + myList.add("Msg"); + myList.add(_list); + myList.add(_map); + myList.add(_uuid); + return myList; + } +} diff --git a/java/client/src/test/java/org/apache/qpid/client/messaging/address/AddressHelperTest.java b/java/client/src/test/java/org/apache/qpid/client/messaging/address/AddressHelperTest.java new file mode 100644 index 0000000000..7401168978 --- /dev/null +++ b/java/client/src/test/java/org/apache/qpid/client/messaging/address/AddressHelperTest.java @@ -0,0 +1,146 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.client.messaging.address; + +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQDestination.AddressOption; +import org.apache.qpid.client.AMQDestination.Binding; +import org.apache.qpid.client.messaging.address.Link.Reliability; +import org.apache.qpid.messaging.Address; +import org.apache.qpid.test.utils.QpidTestCase; + +public class AddressHelperTest extends QpidTestCase +{ + public void testAddressOptions() throws Exception + { + Address addr = Address.parse("queue/test;{create:sender, assert:always, delete:receiver, mode:browse}"); + AddressHelper helper = new AddressHelper(addr); + assertEquals(AddressOption.SENDER,AddressOption.getOption(helper.getCreate())); + assertEquals(AddressOption.ALWAYS,AddressOption.getOption(helper.getAssert())); + assertEquals(AddressOption.RECEIVER,AddressOption.getOption(helper.getDelete())); + assertTrue("'mode' option wasn't read properly",helper.isBrowseOnly()); + } + + public void testNodeProperties() throws Exception + { + Address addr = Address.parse("my-queue;{" + + "node: " + + "{" + + "type: queue ," + + "durable: true ," + + "x-declare: " + + "{" + + "exclusive: true," + + "auto-delete: true," + + "alternate-exchange: 'amq.fanout'," + + "arguments: {" + + "'qpid.max_size': 1000," + + "'qpid.max_count': 100" + + "}" + + "}, " + + "x-bindings: [{exchange : 'amq.direct', queue:my-queue, key : test}, " + + "{exchange : 'amq.fanout', queue:my-queue}," + + "{exchange: 'amq.match', queue:my-queue, arguments: {x-match: any, dep: sales, loc: CA}}," + + "{exchange : 'amq.topic',queue:my-queue, key : 'a.#'}" + + "]" + + + "}" + + "}"); + AddressHelper helper = new AddressHelper(addr); + Node node = helper.getNode(); + assertEquals("'type' property wasn't read properly",AMQDestination.QUEUE_TYPE,helper.getNodeType()); + assertTrue("'durable' property wasn't read properly",node.isDurable()); + assertTrue("'auto-delete' property wasn't read properly",node.isAutoDelete()); + assertTrue("'exclusive' property wasn't read properly",node.isExclusive()); + assertEquals("'alternate-exchange' property wasn't read properly","amq.fanout",node.getAlternateExchange()); + assertEquals("'arguments' in 'x-declare' property wasn't read properly",2,node.getDeclareArgs().size()); + assertEquals("'bindings' property wasn't read properly",4,node.getBindings().size()); + for (Binding binding: node.getBindings()) + { + assertTrue("property 'exchange' in bindings wasn't read properly",binding.getExchange().startsWith("amq.")); + assertEquals("property 'queue' in bindings wasn't read properly","my-queue",binding.getQueue()); + if (binding.getExchange().equals("amq.direct")) + { + assertEquals("'key' property in bindings wasn't read properly","test",binding.getBindingKey()); + } + if (binding.getExchange().equals("amq.match")) + { + assertEquals("'arguments' property in bindings wasn't read properly",3,binding.getArgs().size()); + } + } + } + + public void testLinkProperties() throws Exception + { + Address addr = Address.parse("my-queue;{" + + "link: " + + "{" + + "name: my-queue ," + + "durable: true ," + + "reliability: at-least-once," + + "capacity: {source:10, target:15}," + + "x-declare: " + + "{" + + "exclusive: true," + + "auto-delete: true," + + "alternate-exchange: 'amq.fanout'," + + "arguments: {" + + "'qpid.max_size': 1000," + + "'qpid.max_count': 100" + + "}" + + "}, " + + "x-bindings: [{exchange : 'amq.direct', queue:my-queue, key : test}, " + + "{exchange : 'amq.fanout', queue:my-queue}," + + "{exchange: 'amq.match', queue:my-queue, arguments: {x-match: any, dep: sales, loc: CA}}," + + "{exchange : 'amq.topic',queue:my-queue, key : 'a.#'}" + + "]," + + "x-subscribes:{exclusive: true, arguments: {a:b,x:y}}" + + "}" + + "}"); + + AddressHelper helper = new AddressHelper(addr); + Link link = helper.getLink(); + assertEquals("'name' property wasn't read properly","my-queue",link.getName()); + assertTrue("'durable' property wasn't read properly",link.isDurable()); + assertEquals("'reliability' property wasn't read properly",Reliability.AT_LEAST_ONCE,link.getReliability()); + assertTrue("'auto-delete' property in 'x-declare' wasn't read properly",link.getSubscriptionQueue().isAutoDelete()); + assertTrue("'exclusive' property in 'x-declare' wasn't read properly",link.getSubscriptionQueue().isExclusive()); + assertEquals("'alternate-exchange' property in 'x-declare' wasn't read properly","amq.fanout",link.getSubscriptionQueue().getAlternateExchange()); + assertEquals("'arguments' in 'x-declare' property wasn't read properly",2,link.getSubscriptionQueue().getDeclareArgs().size()); + assertEquals("'bindings' property wasn't read properly",4,link.getBindings().size()); + for (Binding binding: link.getBindings()) + { + assertTrue("property 'exchange' in bindings wasn't read properly",binding.getExchange().startsWith("amq.")); + assertEquals("property 'queue' in bindings wasn't read properly","my-queue",binding.getQueue()); + if (binding.getExchange().equals("amq.direct")) + { + assertEquals("'key' property in bindings wasn't read properly","test",binding.getBindingKey()); + } + if (binding.getExchange().equals("amq.match")) + { + assertEquals("'arguments' property in bindings wasn't read properly",3,binding.getArgs().size()); + } + } + assertTrue("'exclusive' property in 'x-subscribe' wasn't read properly",link.getSubscription().isExclusive()); + assertEquals("'arguments' in 'x-subscribe' property wasn't read properly",2,link.getSubscription().getArgs().size()); + } + +} diff --git a/java/client/src/test/java/org/apache/qpid/client/security/DynamicSaslRegistrarTest.java b/java/client/src/test/java/org/apache/qpid/client/security/DynamicSaslRegistrarTest.java new file mode 100644 index 0000000000..4281984212 --- /dev/null +++ b/java/client/src/test/java/org/apache/qpid/client/security/DynamicSaslRegistrarTest.java @@ -0,0 +1,140 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 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.File; +import java.security.Provider; +import java.security.Security; + +import org.apache.qpid.client.security.DynamicSaslRegistrar.ProviderRegistrationResult; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; + +public class DynamicSaslRegistrarTest extends QpidTestCase +{ + private Provider _registeredProvider; + + public void setUp() throws Exception + { + super.setUp(); + + //If the client provider is already registered, remove it for the duration of the test + _registeredProvider = DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME); + if (_registeredProvider != null) + { + Security.removeProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME); + } + } + + public void tearDown() throws Exception + { + //Remove any provider left behind by the test. + Security.removeProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME); + try + { + //If the client provider was already registered before the test, restore it. + if (_registeredProvider != null) + { + Security.insertProviderAt(_registeredProvider, 1); + } + } + finally + { + super.tearDown(); + } + } + + public void testRegisterDefaultProvider() + { + assertNull("Provider should not yet be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + + ProviderRegistrationResult firstRegistrationResult = DynamicSaslRegistrar.registerSaslProviders(); + assertEquals("Unexpected registration result", ProviderRegistrationResult.SUCCEEDED, firstRegistrationResult); + assertNotNull("Providers should now be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + } + + public void testRegisterDefaultProviderTwice() + { + assertNull("Provider should not yet be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + + DynamicSaslRegistrar.registerSaslProviders(); + assertNotNull("Providers should now be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + + ProviderRegistrationResult result = DynamicSaslRegistrar.registerSaslProviders(); + assertEquals("Unexpected registration result when trying to re-register", ProviderRegistrationResult.EQUAL_ALREADY_REGISTERED, result); + assertNotNull("Providers should still be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + } + + @SuppressWarnings("serial") + public void testRegisterDefaultProviderWhenAnotherIsAlreadyPresentWithDifferentFactories() + { + assertNull("Provider should not be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + + //Add a test provider with the same name, version, info as the default client provider, but with different factory properties (none). + Provider testProvider = new Provider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME, + JCAProvider.QPID_CLIENT_SASL_PROVIDER_VERSION, + JCAProvider.QPID_CLIENT_SASL_PROVIDER_INFO){}; + Security.addProvider(testProvider); + assertSame("Test provider should be registered", testProvider, DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + + //Try to register the default provider now that another with the same name etc (but different factories) + //is already registered, expect it not to be registered as a result. + ProviderRegistrationResult result = DynamicSaslRegistrar.registerSaslProviders(); + assertEquals("Unexpected registration result", ProviderRegistrationResult.DIFFERENT_ALREADY_REGISTERED, result); + + //Verify the test provider is still registered + assertSame("Test provider should still be registered", testProvider, DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + } + + public void testRegisterWithNoFactories() + { + File emptyTempFile = TestFileUtils.createTempFile(this); + + assertNull("Provider should not be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + + //Adjust the location of the properties file to point at an empty file, so no factories are found to register. + setTestSystemProperty("amq.dynamicsaslregistrar.properties", emptyTempFile.getPath()); + + //Try to register the default provider, expect it it not to be registered because there were no factories. + ProviderRegistrationResult result = DynamicSaslRegistrar.registerSaslProviders(); + assertEquals("Unexpected registration result", ProviderRegistrationResult.NO_SASL_FACTORIES, result); + + assertNull("Provider should not be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + } + + public void testRegisterWithMissingFileGetsDefault() + { + //Create a temp file and then delete it, such that we get a path which doesn't exist + File tempFile = TestFileUtils.createTempFile(this); + assertTrue("Failed to delete file", tempFile.delete()); + + assertNull("Provider should not be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + + //Adjust the location of the properties file to point at non-existent file. + setTestSystemProperty("amq.dynamicsaslregistrar.properties", tempFile.getPath()); + + //Try to register the default provider, expect it to fall back to the default in the jar and succeed. + ProviderRegistrationResult result = DynamicSaslRegistrar.registerSaslProviders(); + assertEquals("Unexpected registration result", ProviderRegistrationResult.SUCCEEDED, result); + + assertNotNull("Provider should be registered", DynamicSaslRegistrar.findProvider(JCAProvider.QPID_CLIENT_SASL_PROVIDER_NAME)); + } +} diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java index 412c458247..1e9e5b00a5 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java @@ -120,6 +120,48 @@ public class BrokerDetailsTest extends TestCase { assertTrue(urise.getReason().equals("Illegal character in port number")); } + } + + public void testToStringMasksKeyStorePassword() throws Exception + { + String url = "tcp://localhost:5672?key_store_password='password'"; + BrokerDetails details = new AMQBrokerDetails(url); + + String expectedToString = "tcp://localhost:5672?key_store_password='********'"; + String actualToString = details.toString(); + + assertEquals("Unexpected toString", expectedToString, actualToString); + } + + public void testToStringMasksTrustStorePassword() throws Exception + { + String url = "tcp://localhost:5672?trust_store_password='password'"; + BrokerDetails details = new AMQBrokerDetails(url); + + String expectedToString = "tcp://localhost:5672?trust_store_password='********'"; + String actualToString = details.toString(); + + assertEquals("Unexpected toString", expectedToString, actualToString); + } + + public void testDefaultSsl() throws URLSyntaxException + { + String brokerURL = "tcp://localhost:5672"; + AMQBrokerDetails broker = new AMQBrokerDetails(brokerURL); + + assertNull("default value should be null", broker.getProperty(BrokerDetails.OPTIONS_SSL)); + } + + public void testOverridingSsl() throws URLSyntaxException + { + String brokerURL = "tcp://localhost:5672?ssl='true'"; + AMQBrokerDetails broker = new AMQBrokerDetails(brokerURL); + + assertTrue("value should be true", Boolean.valueOf(broker.getProperty(BrokerDetails.OPTIONS_SSL))); + + brokerURL = "tcp://localhost:5672?ssl='false''&maxprefetch='1'"; + broker = new AMQBrokerDetails(brokerURL); + assertFalse("value should be false", Boolean.valueOf(broker.getProperty(BrokerDetails.OPTIONS_SSL))); } } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java index 392ef1f29b..8c193622e3 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java @@ -30,7 +30,6 @@ import org.apache.qpid.url.URLSyntaxException; public class ConnectionURLTest extends TestCase { - public void testFailoverURL() throws URLSyntaxException { String url = "amqp://ritchiem:bob@/test?brokerlist='tcp://localhost:5672;tcp://fancyserver:3000/',failover='roundrobin?cyclecount='100''"; @@ -252,55 +251,47 @@ public class ConnectionURLTest extends TestCase assertTrue(service.getPort() == 5672); } - public void testSingleTransportDefaultedBrokerWithIPandPort() throws URLSyntaxException + public void testConnectionURLOptionToStringMasksPassword() throws URLSyntaxException { - String url = "amqp://guest:guest@/test?brokerlist='127.0.0.1:1234'"; + String url = "amqp://guest:guest@client/localhost?brokerlist='tcp://localhost:1234'"; + ConnectionURL connectionurl = new AMQConnectionURL(url); + + String expectedToString = "amqp://guest:********@client/localhost?brokerlist='tcp://localhost:1234'"; + String actualToString = connectionurl.toString(); + assertEquals("Unexpected toString form", expectedToString, actualToString); + } + + public void testConnectionURLOptionToStringMasksSslTrustStorePassword() throws URLSyntaxException + { + String url = "amqp://guest:guest@client/vhost?brokerlist='tcp://host:1234?trust_store_password='truststorepassword''"; + ConnectionURL connectionurl = new AMQConnectionURL(url); -// ConnectionURL connectionurl = new AMQConnectionURL(url); -// -// assertTrue(connectionurl.getFailoverMethod() == null); -// assertTrue(connectionurl.getUsername().equals("guest")); -// assertTrue(connectionurl.getPassword().equals("guest")); -// assertTrue(connectionurl.getVirtualHost().equals("/temp")); -// -// -// assertTrue(connectionurl.getBrokerCount() == 1); -// -// BrokerDetails service = connectionurl.getBrokerDetails(0); -// -// assertTrue(service.getTransport().equals("tcp")); -// -// assertTrue(service.getHost().equals("127.0.0.1")); -// assertTrue(service.getPort() == 1234); + String expectedToString = "amqp://guest:********@client/vhost?brokerlist='tcp://host:1234?trust_store_password='********''"; + String actualToString = connectionurl.toString(); + assertEquals("Unexpected toString form", expectedToString, actualToString); + } + + public void testConnectionURLOptionToStringMasksSslKeyStorePassword() throws URLSyntaxException + { + String url = "amqp://guest:guest@client/vhost?brokerlist='tcp://host:1234?key_store_password='keystorepassword1';tcp://host:1235?key_store_password='keystorepassword2''"; + ConnectionURL connectionurl = new AMQConnectionURL(url); + + String expectedToString = "amqp://guest:********@client/vhost?brokerlist='tcp://host:1234?key_store_password='********';tcp://host:1235?key_store_password='********''"; + String actualToString = connectionurl.toString(); + assertEquals("Unexpected toString form", expectedToString, actualToString); } /** * Test for QPID-3662 to ensure the {@code toString()} representation is correct. */ - public void testConnectionURLOptionToString() throws URLSyntaxException + public void testConnectionURLOptionToStringWithMaxPreftech() throws URLSyntaxException { String url = "amqp://guest:guest@client/localhost?maxprefetch='1'&brokerlist='tcp://localhost:1234?tcp_nodelay='true''"; ConnectionURL connectionurl = new AMQConnectionURL(url); - assertNull(connectionurl.getFailoverMethod()); - assertEquals("guest", connectionurl.getUsername()); - assertEquals("guest", connectionurl.getPassword()); - assertEquals("client", connectionurl.getClientName()); - assertEquals("/localhost", connectionurl.getVirtualHost()); - assertEquals("1", connectionurl.getOption("maxprefetch")); - assertTrue(connectionurl.getBrokerCount() == 1); - - BrokerDetails service = connectionurl.getBrokerDetails(0); - assertTrue(service.getTransport().equals("tcp")); - assertTrue(service.getHost().equals("localhost")); - assertTrue(service.getPort() == 1234); - assertTrue(service.getProperties().containsKey("tcp_nodelay")); - assertEquals("true", service.getProperties().get("tcp_nodelay")); - - String nopasswd = "amqp://guest:********@client/localhost?maxprefetch='1'&brokerlist='tcp://localhost:1234?tcp_nodelay='true''"; - String tostring = connectionurl.toString(); - assertEquals(tostring.indexOf("maxprefetch"), tostring.lastIndexOf("maxprefetch")); - assertEquals(nopasswd, tostring); + String expectedToString = "amqp://guest:********@client/localhost?maxprefetch='1'&brokerlist='tcp://localhost:1234?tcp_nodelay='true''"; + String actualToString = connectionurl.toString(); + assertEquals("Unexpected toString form", expectedToString, actualToString); } public void testSingleTransportMultiOptionURL() throws URLSyntaxException @@ -572,9 +563,64 @@ public class ConnectionURLTest extends TestCase connectionurl.getOption(ConnectionURL.OPTIONS_REJECT_BEHAVIOUR)); } - public static junit.framework.Test suite() + /** + * Verify that when the ssl option is not specified, asking for the option returns null, + * such that this can later be used to verify it wasnt specified. + */ + public void testDefaultSsl() throws URLSyntaxException { - return new junit.framework.TestSuite(ConnectionURLTest.class); + String url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672'&foo='bar'"; + ConnectionURL connectionURL = new AMQConnectionURL(url); + + assertNull("default ssl value should be null", connectionURL.getOption(ConnectionURL.OPTIONS_SSL)); + } + + /** + * Verify that when the ssl option is specified, asking for the option returns the value, + * such that this can later be used to verify what value it was specified as. + */ + public void testOverridingSsl() throws URLSyntaxException + { + String url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672'&ssl='true'"; + ConnectionURL connectionURL = new AMQConnectionURL(url); + + assertTrue("value should be true", Boolean.valueOf(connectionURL.getOption(ConnectionURL.OPTIONS_SSL))); + + url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672'&ssl='false'"; + connectionURL = new AMQConnectionURL(url); + + assertFalse("value should be false", Boolean.valueOf(connectionURL.getOption(ConnectionURL.OPTIONS_SSL))); + } + + /** + * Verify that when the {@value ConnectionURL#OPTIONS_VERIFY_QUEUE_ON_SEND} option is not + * specified, asking for the option returns null, such that this can later be used to + * verify it wasn't specified. + */ + public void testDefaultVerifyQueueOnSend() throws URLSyntaxException + { + String url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672'&foo='bar'"; + ConnectionURL connectionURL = new AMQConnectionURL(url); + + assertNull("default ssl value should be null", connectionURL.getOption(ConnectionURL.OPTIONS_SSL)); + } + + /** + * Verify that when the {@value ConnectionURL#OPTIONS_VERIFY_QUEUE_ON_SEND} option is + * specified, asking for the option returns the value, such that this can later be used + * to verify what value it was specified as. + */ + public void testOverridingVerifyQueueOnSend() throws URLSyntaxException + { + String url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672'&verifyQueueOnSend='true'"; + ConnectionURL connectionURL = new AMQConnectionURL(url); + + assertTrue("value should be true", Boolean.valueOf(connectionURL.getOption(ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND))); + + url = "amqp://guest:guest@/test?brokerlist='tcp://localhost:5672'&verifyQueueOnSend='false'"; + connectionURL = new AMQConnectionURL(url); + + assertFalse("value should be false", Boolean.valueOf(connectionURL.getOption(ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND))); } } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java index 9addb0ee71..8f578e6a2f 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java @@ -193,6 +193,126 @@ public class DestinationURLTest extends TestCase assertTrue(dest.getQueueName().equals("test:testQueueD")); } + public void testExchangeOptionsNotPresent() throws URISyntaxException + { + String url = "exchangeClass://exchangeName/Destination/Queue"; + + AMQBindingURL burl = new AMQBindingURL(url); + + assertTrue(url.equals(burl.toString())); + + assertNull(burl.getOption(BindingURL.OPTION_EXCHANGE_DURABLE)); + assertNull(burl.getOption(BindingURL.OPTION_EXCHANGE_AUTODELETE)); + assertNull(burl.getOption(BindingURL.OPTION_EXCHANGE_INTERNAL)); + + class MyTestAMQDestination extends AMQDestination + { + public MyTestAMQDestination(BindingURL url) + { + super(url); + } + public boolean isNameRequired() + { + return false; + } + }; + + AMQDestination dest = new MyTestAMQDestination(burl); + assertFalse(dest.isExchangeAutoDelete()); + assertFalse(dest.isExchangeDurable()); + assertFalse(dest.isExchangeInternal()); + } + + public void testExchangeAutoDeleteOptionPresent() throws URISyntaxException + { + String url = "exchangeClass://exchangeName/Destination/Queue?" + BindingURL.OPTION_EXCHANGE_AUTODELETE + "='true'"; + + AMQBindingURL burl = new AMQBindingURL(url); + + assertTrue(url.equals(burl.toString())); + + assertEquals("true", burl.getOption(BindingURL.OPTION_EXCHANGE_AUTODELETE)); + assertNull(burl.getOption(BindingURL.OPTION_EXCHANGE_DURABLE)); + assertNull(burl.getOption(BindingURL.OPTION_EXCHANGE_INTERNAL)); + + class MyTestAMQDestination extends AMQDestination + { + public MyTestAMQDestination(BindingURL url) + { + super(url); + } + public boolean isNameRequired() + { + return false; + } + }; + + AMQDestination dest = new MyTestAMQDestination(burl); + assertTrue(dest.isExchangeAutoDelete()); + assertFalse(dest.isExchangeDurable()); + assertFalse(dest.isExchangeInternal()); + } + + public void testExchangeDurableOptionPresent() throws URISyntaxException + { + String url = "exchangeClass://exchangeName/Destination/Queue?" + BindingURL.OPTION_EXCHANGE_DURABLE + "='true'"; + + AMQBindingURL burl = new AMQBindingURL(url); + + assertTrue(url.equals(burl.toString())); + + assertEquals("true", burl.getOption(BindingURL.OPTION_EXCHANGE_DURABLE)); + assertNull(burl.getOption(BindingURL.OPTION_EXCHANGE_AUTODELETE)); + assertNull(burl.getOption(BindingURL.OPTION_EXCHANGE_INTERNAL)); + + class MyTestAMQDestination extends AMQDestination + { + public MyTestAMQDestination(BindingURL url) + { + super(url); + } + public boolean isNameRequired() + { + return false; + } + }; + + AMQDestination dest = new MyTestAMQDestination(burl); + assertTrue(dest.isExchangeDurable()); + assertFalse(dest.isExchangeAutoDelete()); + assertFalse(dest.isExchangeInternal()); + } + + public void testExchangeInternalOptionPresent() throws URISyntaxException + { + String url = "exchangeClass://exchangeName/Destination/Queue?" + BindingURL.OPTION_EXCHANGE_INTERNAL + "='true'"; + + AMQBindingURL burl = new AMQBindingURL(url); + + assertTrue(url.equals(burl.toString())); + + assertEquals("true", burl.getOption(BindingURL.OPTION_EXCHANGE_INTERNAL)); + assertNull(burl.getOption(BindingURL.OPTION_EXCHANGE_AUTODELETE)); + assertNull(burl.getOption(BindingURL.OPTION_EXCHANGE_DURABLE)); + + class MyTestAMQDestination extends AMQDestination + { + public MyTestAMQDestination(BindingURL url) + { + super(url); + } + public boolean isNameRequired() + { + return false; + } + }; + + AMQDestination dest = new MyTestAMQDestination(burl); + assertTrue(dest.isExchangeInternal()); + assertFalse(dest.isExchangeDurable()); + assertFalse(dest.isExchangeAutoDelete()); + } + public void testRejectBehaviourPresent() throws URISyntaxException { String url = "exchangeClass://exchangeName/Destination/Queue?rejectbehaviour='server'"; diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java index f199961b6f..4ad9069ba0 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/TestAMQSession.java @@ -124,7 +124,7 @@ public class TestAMQSession extends AMQSession_0_8 return false; } - public void sendConsume(BasicMessageConsumer_0_8 consumer, AMQShortString queueName, AMQProtocolHandler protocolHandler, boolean nowait, int tag) throws AMQException, FailoverException + public void sendConsume(BasicMessageConsumer_0_8 consumer, AMQShortString queueName, boolean nowait, int tag) throws AMQException, FailoverException { } @@ -139,13 +139,13 @@ public class TestAMQSession extends AMQSession_0_8 return null; } - public void sendExchangeDeclare(AMQShortString name, AMQShortString type, AMQProtocolHandler protocolHandler, boolean nowait) throws AMQException, FailoverException + public void sendExchangeDeclare(AMQShortString name, AMQShortString type, boolean nowait, boolean durable, boolean autoDelete, boolean internal) throws AMQException, FailoverException { } public void sendQueueDeclare(AMQDestination amqd, AMQProtocolHandler protocolHandler, - boolean nowait, boolean passive) throws AMQException, FailoverException + boolean passive) throws AMQException, FailoverException { } @@ -189,14 +189,6 @@ public class TestAMQSession extends AMQSession_0_8 { } - public void handleAddressBasedDestination(AMQDestination dest, - boolean isConsumer, - boolean noWait) throws AMQException - { - throw new UnsupportedOperationException("The new addressing based sytanx is " - + "not supported for AMQP 0-8/0-9 versions"); - } - @Override protected void flushAcknowledgments() { diff --git a/java/common.xml b/java/common.xml index 2b61ef08c2..ce5693fd28 100644 --- a/java/common.xml +++ b/java/common.xml @@ -23,7 +23,10 @@ - + + + + @@ -42,7 +45,7 @@ - + @@ -93,6 +96,10 @@ + + + + diff --git a/java/common/bin/qpid-run b/java/common/bin/qpid-run index 1e373340ce..a10766b37a 100755 --- a/java/common/bin/qpid-run +++ b/java/common/bin/qpid-run @@ -88,10 +88,10 @@ SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="-DQPID_WORK=$QPID_WORK" if [ -n "$QPID_LOG_PREFIX" ]; then if [ "X$QPID_LOG_PREFIX" = "XPID" ]; then log $INFO Using pid in qpid log name prefix - LOG_PREFIX=" -Dlogprefix=$$" + LOG_PREFIX="-Dlogprefix=$$" else log $INFO Using qpid logprefix property - LOG_PREFIX=" -Dlogprefix=$QPID_LOG_PREFIX" + LOG_PREFIX="-Dlogprefix=$QPID_LOG_PREFIX" fi SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="${LOG_PREFIX}" fi @@ -99,10 +99,10 @@ fi if [ -n "$QPID_LOG_SUFFIX" ]; then if [ "X$QPID_LOG_SUFFIX" = "XPID" ]; then log $INFO Using pid in qpid log name suffix - LOG_SUFFIX=" -Dlogsuffix=$$" + LOG_SUFFIX="-Dlogsuffix=$$" else log $INFO Using qpig logsuffix property - LOG_SUFFIX=" -Dlogsuffix=$QPID_LOG_SUFFIX" + LOG_SUFFIX="-Dlogsuffix=$QPID_LOG_SUFFIX" fi SYSTEM_PROPS[${#SYSTEM_PROPS[@]}]="${LOG_SUFFIX}" fi diff --git a/java/common/build.xml b/java/common/build.xml index 9caf93c026..e599c840db 100644 --- a/java/common/build.xml +++ b/java/common/build.xml @@ -53,7 +53,15 @@ - + + + + + + + + + @@ -64,15 +72,12 @@ - + - - - - - - + + + diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpClass.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpClass.java new file mode 100644 index 0000000000..26195da2e3 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpClass.java @@ -0,0 +1,197 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintStream; +import java.util.Collection; + +public class AmqpClass implements Printable, NodeAware +{ + + private final AmqpVersionSet _versionSet = new AmqpVersionSet(); + private final AmqpFieldMap _fieldMap = new AmqpFieldMap(); + private final AmqpMethodMap _methodMap = new AmqpMethodMap(); + private final AmqpOrdinalVersionMap _indexMap = new AmqpOrdinalVersionMap(); + + + private final String _name; + private final Generator _generator; + + public AmqpClass(String name, Generator generator) + { + _name = name; + _generator = generator; + } + + public boolean addFromNode(Node classNode, int ordinal, AmqpVersion version) + throws AmqpParseException, AmqpTypeMappingException + { + getVersionSet().add(version); + int index = Utils.getNamedIntegerAttribute(classNode, "index"); + AmqpVersionSet indexVersionSet = getIndexMap().get(index); + if (indexVersionSet != null) + { + indexVersionSet.add(version); + } + else + { + indexVersionSet = new AmqpVersionSet(); + indexVersionSet.add(version); + getIndexMap().put(index, indexVersionSet); + } + NodeList nList = classNode.getChildNodes(); + int fieldCntr = getFieldMap().size(); + for (int i = 0; i < nList.getLength(); i++) + { + Node child = nList.item(i); + if (child.getNodeName().compareTo(Utils.ELEMENT_FIELD) == 0) + { + String fieldName = getGenerator().prepareDomainName(Utils.getNamedAttribute(child, + Utils.ATTRIBUTE_NAME)); + AmqpField thisField = getFieldMap().get(fieldName); + if (thisField == null) + { + thisField = new AmqpField(fieldName, getGenerator()); + getFieldMap().add(fieldName, thisField); + } + if (!thisField.addFromNode(child, fieldCntr++, version)) + { + String className = getGenerator().prepareClassName(Utils.getNamedAttribute(classNode, + Utils.ATTRIBUTE_NAME)); + System.out.println("INFO: Generation supression tag found for field " + + className + "." + fieldName + " - removing."); + thisField.removeVersion(version); + getFieldMap().remove(fieldName); + } + } + else if (child.getNodeName().compareTo(Utils.ELEMENT_METHOD) == 0) + { + String methodName = getGenerator().prepareMethodName(Utils.getNamedAttribute(child, + Utils.ATTRIBUTE_NAME)); + AmqpMethod thisMethod = getMethodMap().get(methodName); + if (thisMethod == null) + { + thisMethod = new AmqpMethod(methodName, getGenerator()); + getMethodMap().put(methodName, thisMethod); + } + if (!thisMethod.addFromNode(child, 0, version)) + { + String className = getGenerator().prepareClassName(Utils.getNamedAttribute(classNode, + Utils.ATTRIBUTE_NAME)); + System.out.println("INFO: Generation supression tag found for method " + + className + "." + methodName + " - removing."); + thisMethod.removeVersion(version); + getMethodMap().remove(methodName); + } + } + else if (child.getNodeName().compareTo(Utils.ELEMENT_CODEGEN) == 0) + { + String value = Utils.getNamedAttribute(child, Utils.ATTRIBUTE_VALUE); + if (value.compareTo("no-gen") == 0) + { + return false; + } + } + } + return true; + } + + public void removeVersion(AmqpVersion version) + { + getIndexMap().removeVersion(version); + getFieldMap().removeVersion(version); + getMethodMap().removeVersion(version); + getVersionSet().remove(version); + } + + public void print(PrintStream out, int marginSize, int tabSize) + { + String margin = Utils.createSpaces(marginSize); + String tab = Utils.createSpaces(tabSize); + out.println(margin + "[C] " + getName() + ": " + getVersionSet()); + + for (Integer thisIndex : getIndexMap().keySet()) + { + AmqpVersionSet indexVersionSet = getIndexMap().get(thisIndex); + out.println(margin + tab + "[I] " + thisIndex + indexVersionSet); + } + + for (String thisFieldName : getFieldMap().keySet()) + { + AmqpField thisField = getFieldMap().get(thisFieldName); + thisField.print(out, marginSize + tabSize, tabSize); + } + + for (String thisMethodName : getMethodMap().keySet()) + { + AmqpMethod thisMethod = getMethodMap().get(thisMethodName); + thisMethod.print(out, marginSize + tabSize, tabSize); + } + } + + public AmqpVersionSet getVersionSet() + { + return _versionSet; + } + + public Generator getGenerator() + { + return _generator; + } + + + public AmqpFieldMap getFieldMap() + { + return _fieldMap; + } + + + public AmqpMethodMap getMethodMap() + { + return _methodMap; + } + + public Collection getMethods() + { + return getMethodMap().values(); + } + + + public String getName() + { + return _name; + } + + + public AmqpOrdinalVersionMap getIndexMap() + { + return _indexMap; + } + + public SingleVersionClass asSingleVersionClass(AmqpVersion version) + { + return new SingleVersionClass(this,version, _generator); + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java new file mode 100644 index 0000000000..a27a50d07e --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpClassMap.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpClassMap extends TreeMap +{ + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpConstant.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpConstant.java new file mode 100644 index 0000000000..df5bc6c362 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpConstant.java @@ -0,0 +1,191 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.io.PrintStream; +import java.util.TreeMap; + +/** + * @author kpvdr + * Class to represent the <constant> declaration within the AMQP specification. + * Currently, only integer values exist within the specification, however looking forward + * to other possible types in the future, string and double types are also supported. + *

+ * The <constant> declaration in the specification contains only two attributes: + * name and value. + *

+ * The value of the constant is mapped against the version(s) for which the name is defined. + * This allows for a change in the value rather than the name only from one version to the next. + */ +@SuppressWarnings("serial") +public class AmqpConstant extends TreeMap + implements Printable, VersionConsistencyCheck, Comparable +{ + /** + * Constant name as defined by the name attribute of the <constant> declaration. + */ + private final String _name; + + /** + * Set of versions for which this constant name is defined. + */ + private final AmqpVersionSet _versionSet; + + /** + * Constructor + * + * @param name Constant name as defined by the name attribute of the <constant> declaration. + * @param value Constant value as defined by the value attribute of the <constant> declaration. + * @param version AMQP version for which this constant is defined + */ + public AmqpConstant(String name, String value, AmqpVersion version) + { + _name = name; + _versionSet = new AmqpVersionSet(version); + AmqpVersionSet valueVersionSet = new AmqpVersionSet(version); + put(value, valueVersionSet); + } + + + /** + * Get the name of this constant. + * + * @return Name of this constant, being the name attribute of the <constant> declaration + * represented by this class. + */ + public String getName() + { + return _name; + } + + /** + * Get the value of this constant as a String. + * + * @param version AMQP version for which this value is required. + * @return Value of this constant, being the value attribute of the <constant> declaration + * represented by this class. + * @throws AmqpTypeMappingException when a value is requested for a version for which it is not + * defined in the AMQP specifications. + */ + public String getStringValue(AmqpVersion version) + throws AmqpTypeMappingException + { + for (String thisValue : keySet()) + { + AmqpVersionSet versionSet = get(thisValue); + if (versionSet.contains(version)) + { + return thisValue; + } + } + throw new AmqpTypeMappingException("Unable to find value for constant \"" + getName() + + "\" for version " + version.toString() + "."); + } + + /** + * Get the value of this constant as an integer. + * + * @param version AMQP version for which this value is required. + * @return Value of this constant, being the value attribute of the <constant> declaration + * represented by this class. + * @throws AmqpTypeMappingException when a value is requested for a version for which it is not + * defined in the AMQP specifications. + */ + public int getIntegerValue(AmqpVersion version) + throws AmqpTypeMappingException + { + return Integer.parseInt(getStringValue(version)); + } + + /** + * Get the value of this constant as a double. + * + * @param version AMQP version for which this value is required. + * @return Value of this constant, being the value attribute of the <constant> declaration + * represented by this class. + * @throws AmqpTypeMappingException when a value is requested for a version for which it is not + * defined in the AMQP specifications. + */ + public double getDoubleValue(AmqpVersion version) + throws AmqpTypeMappingException + { + return Double.parseDouble(getStringValue(version)); + } + + /** + * Get the version set for this constant. It contains the all the versions for which this + * constant name exists. + * + * @return Set of versions for which this constant exists. + */ + public AmqpVersionSet getVersionSet() + { + return _versionSet; + } + + /* (non-Javadoc) + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ + + public int compareTo(AmqpConstant other) + { + int res = getName().compareTo(other.getName()); + if (res != 0) + { + return res; + } + return getVersionSet().compareTo(other.getVersionSet()); + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.VersionConsistencyCheck#isVersionConsistent(org.apache.qpid.gentools.AmqpVersionSet) + */ + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (size() != 1) + { + return false; + } + return get(firstKey()).equals(globalVersionSet); + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.Printable#print(java.io.PrintStream, int, int) + */ + public void print(PrintStream out, int marginSize, int tabSize) + { + String margin = Utils.createSpaces(marginSize); + String tab = Utils.createSpaces(tabSize); + if (size() == 1) + { + out.println(margin + tab + "[C] " + getName() + " = \"" + firstKey() + "\" " + getVersionSet()); + } + else + { + out.println(margin + tab + "[C] " + getName() + ": " + getVersionSet()); + for (String thisValue : keySet()) + { + out.println(margin + tab + tab + "= \"" + thisValue + "\" " + get(thisValue)); + } + } + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java new file mode 100644 index 0000000000..ab8b8be61e --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpConstantSet.java @@ -0,0 +1,152 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintStream; +import java.util.Iterator; +import java.util.TreeSet; + +/** + * @author kpvdr + * This class implements a set collection for {@link AmqpConstant AmqpConstant} objects, being the collection + * of constants accumulated from various AMQP specification files processed. Each name occurs once only in the set. + * The {@link AmqpConstant AmqpConstant} objects (derived from {@link java.util.TreeMap TreeMap}) keep track of + * the value and version(s) assigned to this name. + */ +@SuppressWarnings("serial") +public class AmqpConstantSet implements Printable, NodeAware //, Comparable +{ + private final LanguageConverter _converter; + private final TreeSet _constants = new TreeSet(); + private final AmqpVersionSet _versionSet = new AmqpVersionSet(); + + public AmqpConstantSet(LanguageConverter converter) + { + _converter = converter; + + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.NodeAware#addFromNode(org.w3c.dom.Node, int, org.apache.qpid.gentools.AmqpVersion) + */ + public boolean addFromNode(Node node, int ordinal, AmqpVersion version) + throws AmqpParseException, AmqpTypeMappingException + { + _versionSet.add(version); + NodeList nodeList = node.getChildNodes(); + for (int i = 0; i < nodeList.getLength(); i++) + { + Node childNode = nodeList.item(i); + if (childNode.getNodeName().compareTo(Utils.ELEMENT_CONSTANT) == 0) + { + String name = getConverter().prepareConstantName(Utils.getNamedAttribute(childNode, Utils.ATTRIBUTE_NAME)); + String value = Utils.getNamedAttribute(childNode, Utils.ATTRIBUTE_VALUE); + // Find this name in the existing set of objects + boolean foundName = false; + Iterator cItr = _constants.iterator(); + while (cItr.hasNext() && !foundName) + { + AmqpConstant thisConstant = cItr.next(); + if (name.compareTo(thisConstant.getName()) == 0) + { + foundName = true; + thisConstant.getVersionSet().add(version); + // Now, find the value in the map + boolean foundValue = false; + for (String thisValue : thisConstant.keySet()) + { + if (value.compareTo(thisValue) == 0) + { + foundValue = true; + // Add this version to existing version set. + AmqpVersionSet versionSet = thisConstant.get(thisValue); + versionSet.add(version); + } + } + // Check that the value was found - if not, add it + if (!foundValue) + { + thisConstant.put(value, new AmqpVersionSet(version)); + } + } + } + // Check that the name was found - if not, add it + if (!foundName) + { + _constants.add(new AmqpConstant(name, value, version)); + } + } + } + return true; + } + + /* (non-Javadoc) + * @see org.apache.qpid.gentools.Printable#print(java.io.PrintStream, int, int) + */ + public void print(PrintStream out, int marginSize, int tabSize) + { + out.println(Utils.createSpaces(marginSize) + "Constants: "); + for (AmqpConstant thisAmqpConstant : _constants) + { + thisAmqpConstant.print(out, marginSize, tabSize); + } + } + + /* (non-Javadoc) + * @see java.lang.Comparable#compareTo(java.lang.Object) + */ +// public int compareTo(AmqpConstantSet other) +// { +// int res = size() - other.size(); +// if (res != 0) +// return res; +// Iterator cItr = iterator(); +// Iterator oItr = other.iterator(); +// while (cItr.hasNext() && oItr.hasNext()) +// { +// AmqpConstant constant = cItr.next(); +// AmqpConstant oConstant = oItr.next(); +// res = constant.compareTo(oConstant); +// if (res != 0) +// return res; +// } +// return 0; +// } + + public Iterable getContstants() + { + return _constants; + } + + public AmqpVersionSet getVersionSet() + { + return _versionSet; + } + + public LanguageConverter getConverter() + { + return _converter; + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpDomain.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpDomain.java new file mode 100644 index 0000000000..ba8552a6a6 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpDomain.java @@ -0,0 +1,89 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.io.PrintStream; +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpDomain extends TreeMap implements Printable +{ + private final String _domainName; + + public AmqpDomain(String domainName) + { + _domainName = domainName; + } + + public void addDomain(String domainType, AmqpVersion version) throws AmqpParseException + { + AmqpVersionSet versionSet = get(domainType); + if (versionSet == null) // First time, create new entry + { + versionSet = new AmqpVersionSet(); + put(domainType, versionSet); + } + versionSet.add(version); + } + + public String getDomainType(AmqpVersion version) + throws AmqpTypeMappingException + { + for (String thisDomainType : keySet()) + { + AmqpVersionSet versionSet = get(thisDomainType); + if (versionSet.contains(version)) + { + return thisDomainType; + } + } + throw new AmqpTypeMappingException("Unable to find version " + version + "."); + } + + public boolean hasVersion(String type, AmqpVersion v) + { + AmqpVersionSet vs = get(type); + if (vs == null) + { + return false; + } + return vs.contains(v); + } + + public void print(PrintStream out, int marginSize, int tabSize) + { + String margin = Utils.createSpaces(marginSize); + String tab = Utils.createSpaces(tabSize); + out.println(margin + getDomainName() + ":"); + + for (String thisDomainType : keySet()) + { + AmqpVersionSet vs = get(thisDomainType); + out.println(margin + tab + thisDomainType + " : " + vs.toString()); + } + } + + public String getDomainName() + { + return _domainName; + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpDomainMap.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpDomainMap.java new file mode 100644 index 0000000000..0cd9d214bd --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpDomainMap.java @@ -0,0 +1,128 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintStream; +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpDomainMap extends TreeMap implements Printable, NodeAware +{ + private final LanguageConverter _converter; + + public AmqpDomainMap(LanguageConverter converter) + { + _converter = converter; + + } + + public boolean addFromNode(Node n, int o, AmqpVersion v) + throws AmqpParseException, AmqpTypeMappingException + { + NodeList nl = n.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) + { + Node c = nl.item(i); + // All versions 0.9 and greater use for all domains + if (c.getNodeName().compareTo(Utils.ELEMENT_DOMAIN) == 0) + { + String domainName = getConverter().prepareDomainName(Utils.getNamedAttribute(c, Utils.ATTRIBUTE_NAME)); + String type = Utils.getNamedAttribute(c, Utils.ATTRIBUTE_TYPE); + AmqpDomain thisDomain = get(domainName); + if (thisDomain == null) + { + thisDomain = new AmqpDomain(domainName); + put(domainName, thisDomain); + } + thisDomain.addDomain(type, v); + } + // Version(s) 0.8 and earlier use for all complex domains and use + // attribute for simple types. Add these simple types to + // domain list - but beware of duplicates! + else if (c.getNodeName().compareTo(Utils.ELEMENT_FIELD) == 0) + { + try + { + String type = getConverter().prepareDomainName(Utils.getNamedAttribute(c, Utils.ATTRIBUTE_TYPE)); + AmqpDomain thisDomain = get(type); + if (thisDomain == null) + { + thisDomain = new AmqpDomain(type); + put(type, thisDomain); + } + if (!thisDomain.hasVersion(type, v)) + { + thisDomain.addDomain(type, v); + } + } + catch (AmqpParseException e) + { + } // Ignore fields without type attribute + } + else if (c.getNodeName().compareTo(Utils.ELEMENT_CLASS) == 0 || + c.getNodeName().compareTo(Utils.ELEMENT_METHOD) == 0) + { + addFromNode(c, 0, v); + } + } + return true; + } + + public String getDomainType(String domainName, AmqpVersion version) + { + AmqpDomain domainType = get(domainName); + // For AMQP 8.0, primitive types were not described as domains, so + // return itself as the type. + if (domainType == null) + { + return domainName; + } + try + { + return domainType.getDomainType(version); + } + catch (AmqpTypeMappingException e) + { + throw new AmqpTypeMappingException("Unable to find domain type for domain \"" + domainName + + "\" version " + version + "."); + } + } + + + public void print(PrintStream out, int marginSize, int tabSize) + { + out.println(Utils.createSpaces(marginSize) + "Domain Map:"); + for (String thisDomainName : keySet()) + { + AmqpDomain domain = get(thisDomainName); + domain.print(out, marginSize + tabSize, tabSize); + } + } + + public LanguageConverter getConverter() + { + return _converter; + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java new file mode 100644 index 0000000000..e39550b96f --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpDomainVersionMap.java @@ -0,0 +1,62 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.ArrayList; +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpDomainVersionMap extends TreeMap implements VersionConsistencyCheck +{ + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (size() != 1) + { + return false; + } + return get(firstKey()).equals(globalVersionSet); + } + + public boolean removeVersion(AmqpVersion version) + { + Boolean res = false; + ArrayList removeList = new ArrayList(); + for (String domainName : keySet()) + { + AmqpVersionSet versionSet = get(domainName); + if (versionSet.contains(version)) + { + versionSet.remove(version); + if (versionSet.isEmpty()) + { + removeList.add(domainName); + } + res = true; + } + } + // Get rid of domains no longer in use + for (String domainName : removeList) + { + remove(domainName); + } + return res; + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpField.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpField.java new file mode 100644 index 0000000000..7c721cf913 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpField.java @@ -0,0 +1,269 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class AmqpField implements Printable, NodeAware, VersionConsistencyCheck +{ + + private final AmqpVersionSet _versionSet = new AmqpVersionSet(); + private final AmqpDomainVersionMap _domainMap = new AmqpDomainVersionMap(); + private final AmqpOrdinalVersionMap _ordinalMap = new AmqpOrdinalVersionMap(); + + private final String _name; + private final Generator _generator; + + private final Map _versionToDomainMap = new HashMap(); + private final Map _versionToOrdinalMap = new HashMap(); + + + public AmqpField(String name, Generator generator) + { + _name = name; + _generator = generator; + + } + + public boolean addFromNode(Node fieldNode, int ordinal, AmqpVersion version) + throws AmqpParseException, AmqpTypeMappingException + { + _versionSet.add(version); + String domainType; + // Early versions of the spec (8.0) used the "type" attribute instead of "domain" for some fields. + try + { + domainType = _generator.prepareDomainName(Utils.getNamedAttribute(fieldNode, Utils.ATTRIBUTE_DOMAIN)); + } + catch (AmqpParseException e) + { + domainType = _generator.prepareDomainName(Utils.getNamedAttribute(fieldNode, Utils.ATTRIBUTE_TYPE)); + } + AmqpVersionSet thisVersionList = _domainMap.get(domainType); + if (thisVersionList == null) // First time, create new entry + { + thisVersionList = new AmqpVersionSet(); + _domainMap.put(domainType, thisVersionList); + } + + _versionToDomainMap.put(version, domainType); + _versionToOrdinalMap.put(version, ordinal); + + thisVersionList.add(version); + thisVersionList = _ordinalMap.get(ordinal); + if (thisVersionList == null) // First time, create new entry + { + thisVersionList = new AmqpVersionSet(); + _ordinalMap.put(ordinal, thisVersionList); + } + thisVersionList.add(version); + NodeList nList = fieldNode.getChildNodes(); + for (int i = 0; i < nList.getLength(); i++) + { + Node child = nList.item(i); + if (child.getNodeName().compareTo(Utils.ELEMENT_CODEGEN) == 0) + { + String value = Utils.getNamedAttribute(child, Utils.ATTRIBUTE_VALUE); + if (value.compareTo("no-gen") == 0) + { + return false; + } + } + } + return true; + } + + public void removeVersion(AmqpVersion version) + { + _domainMap.removeVersion(version); + _ordinalMap.removeVersion(version); + _versionSet.remove(version); + } + + public boolean isCodeTypeConsistent(LanguageConverter converter) + throws AmqpTypeMappingException + { + if (_domainMap.size() == 1) + { + return true; // By definition + } + ArrayList codeTypeList = new ArrayList(); + for (String thisDomainName : _domainMap.keySet()) + { + AmqpVersionSet versionSet = _domainMap.get(thisDomainName); + String codeType = converter.getGeneratedType(thisDomainName, versionSet.first()); + if (!codeTypeList.contains(codeType)) + { + codeTypeList.add(codeType); + } + } + return codeTypeList.size() == 1; + } + + public boolean isConsistent(Generator generator) + throws AmqpTypeMappingException + { + if (!isCodeTypeConsistent(generator)) + { + return false; + } + if (_ordinalMap.size() != 1) + { + return false; + } + // Since the various doamin names map to the same code type, add the version occurrences + // across all domains to see we have all possible versions covered + int vCntr = 0; + for (String thisDomainName : _domainMap.keySet()) + { + vCntr += _domainMap.get(thisDomainName).size(); + } + return vCntr == generator.getVersionSet().size(); + } + + public boolean isTypeAndNameConsistent(Generator generator) + throws AmqpTypeMappingException + { + if (!isCodeTypeConsistent(generator)) + { + return false; + } + // Since the various doamin names map to the same code type, add the version occurrences + // across all domains to see we have all possible versions covered + int vCntr = 0; + for (String thisDomainName : _domainMap.keySet()) + { + vCntr += _domainMap.get(thisDomainName).size(); + } + return vCntr == getVersionSet().size(); + } + + + public void print(PrintStream out, int marginSize, int tabSize) + { + String margin = Utils.createSpaces(marginSize); + out.println(margin + "[F] " + _name + ": " + _versionSet); + + for (Integer thisOrdinal : _ordinalMap.keySet()) + { + AmqpVersionSet versionList = _ordinalMap.get(thisOrdinal); + out.println(margin + " [O] " + thisOrdinal + " : " + versionList.toString()); + } + + for (String thisDomainName : _domainMap.keySet()) + { + AmqpVersionSet versionList = _domainMap.get(thisDomainName); + out.println(margin + " [D] " + thisDomainName + " : " + versionList.toString()); + } + } + + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (!_versionSet.equals(globalVersionSet)) + { + return false; + } + if (!_domainMap.isVersionConsistent(globalVersionSet)) + { + return false; + } + if (!_ordinalMap.isVersionConsistent(globalVersionSet)) + { + return false; + } + return true; + } + + + public boolean isVersionInterfaceConsistent(AmqpVersionSet globalVersionSet) + { + if (!_versionSet.equals(globalVersionSet)) + { + return false; + } + if (!_domainMap.isVersionConsistent(globalVersionSet)) + { + return false; + } + if (!_ordinalMap.isVersionConsistent(globalVersionSet)) + { + return false; + } + return true; + } + + public String getDomain(AmqpVersion version) + { + return _versionToDomainMap.get(version); + } + + public String getConsistentNativeType() + { + return _generator.getNativeType(_generator.getDomainType(getDomain(_versionSet.first()),_versionSet.first())); + } + + public int getOrdinal(AmqpVersion version) + { + return _versionToOrdinalMap.get(version); + } + + public AmqpVersionSet getVersionSet() + { + return _versionSet; + } + + public AmqpDomainVersionMap getDomainMap() + { + return _domainMap; + } + + public AmqpOrdinalVersionMap getOrdinalMap() + { + return _ordinalMap; + } + + public String getName() + { + return _name; + } + + public LanguageConverter getGenerator() + { + return _generator; + } + + public Map getVersionToDomainMap() + { + return _versionToDomainMap; + } + + public Map getVersionToOrdinalMap() + { + return _versionToOrdinalMap; + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpFieldMap.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpFieldMap.java new file mode 100644 index 0000000000..0bb5e03a61 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpFieldMap.java @@ -0,0 +1,452 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpFieldMap implements VersionConsistencyCheck +{ + + private final TreeMap _map = new TreeMap(); + + private final AmqpVersionSet _versionSet = new AmqpVersionSet(); + + public void removeVersion(AmqpVersion version) + { + String[] fieldNameArray = new String[size()]; + _map.keySet().toArray(fieldNameArray); + Iterator> iter = _map.entrySet().iterator(); + + while (iter.hasNext()) + { + Entry entry = iter.next(); + entry.getValue().removeVersion(version); + iter.remove(); + } + } + + public int size() + { + return _map.size(); + + } + + public AmqpFieldMap getFieldMapForOrdinal(int ordinal) + { + AmqpFieldMap newMap = new AmqpFieldMap(); + for (AmqpField field : _map.values()) + { + + TreeMap ordinalMap = field.getOrdinalMap(); + AmqpVersionSet ordinalVersions = ordinalMap.get(ordinal); + if (ordinalVersions != null) + { + newMap.add(field.getName(), field); + } + } + return newMap; + } + + public void add(String name, AmqpField field) + { + _versionSet.addAll(field.getVersionSet()); + _map.put(name, field); + } + + public AmqpOrdinalFieldMap getMapForVersion(AmqpVersion version, boolean codeTypeFlag, + LanguageConverter converter) + { + // TODO: REVIEW THIS! There may be a bug here that affects C++ generation (only with >1 version)... + // If version == null (a common scenario) then the version map is built up on the + // basis of first found item, and ignores other version variations. + // This should probably be disallowed by throwing an NPE, as AmqpOrdinalFieldMap cannot + // represent these possibilities. + // *OR* + // Change the structure of AmqpOrdianlFieldMap to allow for the various combinations that + // will result from version variation - but that is what AmqpFieldMap is... :-$ + AmqpOrdinalFieldMap ordinalFieldMap = new AmqpOrdinalFieldMap(); + for (AmqpField field : _map.values()) + { + + if (version == null || field.getVersionSet().contains(version)) + { + // 1. Search for domain name in field domain map with version that matches + String domain = ""; + boolean dFound = false; + for (String thisDomainName : field.getDomainMap().keySet()) + { + domain = thisDomainName; + AmqpVersionSet versionSet = field.getDomainMap().get(domain); + if (version == null || versionSet.contains(version)) + { + if (codeTypeFlag) + { + domain = converter.getGeneratedType(domain, version); + } + dFound = true; + } + } + + // 2. Search for ordinal in field ordianl map with version that matches + int ordinal = -1; + boolean oFound = false; + for (Integer thisOrdinal : field.getOrdinalMap().keySet()) + { + ordinal = thisOrdinal; + AmqpVersionSet versionSet = field.getOrdinalMap().get(ordinal); + if (version == null || versionSet.contains(version)) + { + oFound = true; + } + } + + if (dFound && oFound) + { + String[] fieldDomainPair = {field.getName(), domain}; + ordinalFieldMap.put(ordinal, fieldDomainPair); + } + } + } + return ordinalFieldMap; + } + + public boolean isDomainConsistent(Generator generator, AmqpVersionSet versionSet) + throws AmqpTypeMappingException + { + if (size() != 1) // Only one field for this ordinal + { + return false; + } + return _map.get(_map.firstKey()).isConsistent(generator); + } + + public int getNumFields(AmqpVersion version) + { + int fCntr = 0; + for (AmqpField field : _map.values()) + { + + if (field.getVersionSet().contains(version)) + { + fCntr++; + } + } + return fCntr; + } + + public String parseFieldMap(CommandGenerateMethod commonGenerateMethod, MangledGenerateMethod mangledGenerateMethod, + int indentSize, int tabSize, LanguageConverter converter) + { + String indent = Utils.createSpaces(indentSize); + String cr = Utils.LINE_SEPARATOR; + StringBuffer sb = new StringBuffer(); + + if (commonGenerateMethod == null) + { + // Generate warnings in code if required methods are null. + sb.append(indent + "/*********************************************************" + cr); + sb.append(indent + " * WARNING: Generated code could be missing." + cr); + sb.append(indent + " * In call to parseFieldMap(), generation method was null." + cr); + sb.append(indent + " * Check for NoSuchMethodException on startup." + cr); + sb.append(indent + " *********************************************************/" + cr); + } + + Iterator> itr = _map.entrySet().iterator(); + while (itr.hasNext()) + { + Entry entry = itr.next(); + String fieldName = entry.getKey(); + AmqpField field = entry.getValue(); + if (field.isCodeTypeConsistent(converter)) + { + // All versions identical - Common declaration + String domainName = field.getDomainMap().firstKey(); + AmqpVersionSet versionSet = field.getDomainMap().get(domainName); + String codeType = converter.getGeneratedType(domainName, versionSet.first()); + if (commonGenerateMethod != null) + { + sb.append(commonGenerateMethod.generate(codeType, field, versionSet, + indentSize, tabSize, itr.hasNext())); + } + } + else if (mangledGenerateMethod != null) // Version-mangled + { + sb.append(mangledGenerateMethod.generate(field, indentSize, tabSize, + itr.hasNext())); + } + } + return sb.toString(); + } + + public String parseFieldMapOrdinally(GenerateMethod generateMethod, BitFieldGenerateMethod bitGenerateMethod, + int indentSize, int tabSize, Generator codeGenerator) + { + String indent = Utils.createSpaces(indentSize); + String cr = Utils.LINE_SEPARATOR; + StringBuffer sb = new StringBuffer(); + + // Generate warnings in code if required methods are null. + if (generateMethod == null || bitGenerateMethod == null) + { + sb.append(indent + "/***********************************************" + cr); + sb.append(indent + " * WARNING: In call to parseFieldMapOrdinally():" + cr); + if (generateMethod == null) + { + sb.append(indent + " * => generateMethod is null." + cr); + } + if (bitGenerateMethod == null) + { + sb.append(indent + " * => bitGenerateMethod is null." + cr); + } + sb.append(indent + " * Generated code could be missing." + cr); + sb.append(indent + " * Check for NoSuchMethodException on startup." + cr); + sb.append(indent + " ***********************************************/" + cr); + } + + /* We must process elements in ordinal order because adjacent booleans (bits) + * must be combined into a single byte (in groups of up to 8). Start with shared + * declarations until an ordinal divergence is found. (For most methods where + * there is no difference between versions, this will simplify the generated + * code. */ + + ArrayList bitFieldList = new ArrayList(); + boolean ordinalDivergenceFlag = false; + int ordinal = 0; + while (ordinal < size() && !ordinalDivergenceFlag) + { + /* Since the getFieldMapOrdinal() function may map more than one Field to + * an ordinal, the number of ordinals may be less than the total number of + * fields in the fieldMap. Check for empty fieldmaps... */ + AmqpFieldMap ordinalFieldMap = getFieldMapForOrdinal(ordinal); + if (ordinalFieldMap.size() > 0) + { + if (ordinalFieldMap.isDomainConsistent(codeGenerator, getVersionSet())) + { + String fieldName = ordinalFieldMap.getFirstFieldName(); + String domain = ordinalFieldMap._map.get(fieldName).getDomainMap().firstKey(); + + String domainType = codeGenerator.getDomainType(domain, + codeGenerator.getVersionSet().first()); + + if (domainType.compareTo("bit") == 0) + { + bitFieldList.add(fieldName); + } + else if (bitFieldList.size() > 0) + { + // End of bit types - handle deferred bit type generation + if (bitGenerateMethod != null) + { + sb.append(bitGenerateMethod.generate(bitFieldList, ordinal, + indentSize, tabSize)); + } + bitFieldList.clear(); + } + if (!ordinalDivergenceFlag) + { + // Defer generation of bit types until all adjacent bits have been + // accounted for. + if (bitFieldList.size() == 0 && generateMethod != null) + { + sb.append(generateMethod.generate(domainType, fieldName, ordinal, + indentSize, tabSize)); + } + } + ordinal++; + } + else + { + ordinalDivergenceFlag = true; + } + } + } + + // Check if there is still more to do under a version-specific breakout + if (ordinalDivergenceFlag && ordinal < size()) + { + // 1. Cycle through all versions in order, create outer if(version) structure + AmqpVersion[] versionArray = new AmqpVersion[getVersionSet().size()]; + getVersionSet().toArray(versionArray); + for (int v = 0; v < versionArray.length; v++) + { + sb.append(indent); + if (v > 0) + { + sb.append("else "); + } + sb.append("if (major == " + versionArray[v].getMajor() + " && minor == " + + versionArray[v].getMinor() + ")" + cr); + sb.append(indent + "{" + cr); + + // 2. Cycle though each ordinal from where we left off in the loop above. + ArrayList bitFieldList2 = new ArrayList(bitFieldList); + for (int o = ordinal; o < size(); o++) + { + AmqpFieldMap ordinalFieldMap = getFieldMapForOrdinal(o); + if (ordinalFieldMap.size() > 0) + { + // 3. Cycle through each of the fields that have this ordinal. + Iterator> i = ordinalFieldMap._map.entrySet().iterator(); + while (i.hasNext()) + { + + Map.Entry entry = i.next(); + AmqpField field = entry.getValue(); + String fieldName = entry.getKey(); + + // 4. Some fields may have more than one ordinal - match by both + // ordinal and version. + Iterator j = field.getOrdinalMap().keySet().iterator(); + while (j.hasNext()) + { + int thisOrdinal = j.next(); + AmqpVersionSet v1 = field.getOrdinalMap().get(thisOrdinal); + if (thisOrdinal == o && v1.contains(versionArray[v])) + { + // 5. Now get the domain for this version + int domainCntr = 0; + Iterator k = field.getDomainMap().keySet().iterator(); + while (k.hasNext()) + { + // Mangle domain-divergent field names + String mangledFieldName = fieldName; + if (field.getDomainMap().size() > 1) + { + mangledFieldName += "_" + (domainCntr++); + } + String domainName = k.next(); + AmqpVersionSet v2 = field.getDomainMap().get(domainName); + if (v2.contains(versionArray[v])) + { + // 6. (Finally!!) write the declaration + String domainType = codeGenerator.getDomainType(domainName, + versionArray[v]); + if (domainType.compareTo("bit") == 0) + { + bitFieldList2.add(mangledFieldName); + } + else if (bitFieldList2.size() > 0) + { + // End of bit types - handle deferred bit type generation + if (bitGenerateMethod != null) + { + sb.append(bitGenerateMethod.generate( + bitFieldList2, o, indentSize + tabSize, + tabSize)); + } + bitFieldList2.clear(); + } + // Defer generation of bit types until all adjacent bits have + // been accounted for. + if (bitFieldList2.size() == 0 && generateMethod != null) + { + sb.append(generateMethod.generate(domainType, + mangledFieldName, o, indentSize + tabSize, tabSize)); + } + } + } + } + } + } + } + } + // Check for remaining deferred bits + if (bitFieldList2.size() > 0 && bitGenerateMethod != null) + { + sb.append(bitGenerateMethod.generate(bitFieldList2, size(), + indentSize + tabSize, tabSize)); + } + sb.append(indent + "}" + cr); + } + } + // Check for remaining deferred bits + else if (bitFieldList.size() > 0 && bitGenerateMethod != null) + { + sb.append(bitGenerateMethod.generate(bitFieldList, size(), + indentSize, tabSize)); + } + return sb.toString(); + } + + private String getFirstFieldName() + { + return _map.firstKey(); + } + + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + for (String thisFieldName : _map.keySet()) + { + AmqpField field = _map.get(thisFieldName); + if (!field.isVersionConsistent(globalVersionSet)) + { + return false; + } + } + return true; + } + + public boolean isVersionInterfaceConsistent(AmqpVersionSet globalVersionSet) + { + for (String thisFieldName : _map.keySet()) + { + AmqpField field = _map.get(thisFieldName); + if (!field.isVersionInterfaceConsistent(globalVersionSet)) + { + return false; + } + } + return true; + } + + + public AmqpVersionSet getVersionSet() + { + return _versionSet; + } + + public Collection values() + { + return _map.values(); + } + + public AmqpField get(String fieldName) + { + return _map.get(fieldName); + } + + public void remove(String fieldName) + { + _map.remove(fieldName); + } + + public Set keySet() + { + return _map.keySet(); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java new file mode 100644 index 0000000000..5993a1b715 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpFlagMap.java @@ -0,0 +1,77 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.ArrayList; +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpFlagMap extends TreeMap implements VersionConsistencyCheck +{ + public boolean isSet() + { + return containsKey(true); + } + + public String toString() + { + AmqpVersionSet versionSet = get(true); + if (versionSet != null) + { + return versionSet.toString(); + } + return ""; + } + + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (size() != 1) + { + return false; + } + return get(firstKey()).equals(globalVersionSet); + } + + public boolean removeVersion(AmqpVersion version) + { + Boolean res = false; + ArrayList removeList = new ArrayList(); + for (Boolean flag : keySet()) + { + AmqpVersionSet versionSet = get(flag); + if (versionSet.contains(version)) + { + versionSet.remove(version); + if (versionSet.isEmpty()) + { + removeList.add(flag); + } + res = true; + } + } + // Get rid of flags no longer in use + for (Boolean flag : removeList) + { + remove(flag); + } + return res; + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpMethod.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpMethod.java new file mode 100644 index 0000000000..4ec39b209e --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpMethod.java @@ -0,0 +1,351 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Collection; +import java.util.concurrent.atomic.AtomicInteger; + +public class AmqpMethod implements Printable, NodeAware, VersionConsistencyCheck +{ + private final AmqpVersionSet _versionSet = new AmqpVersionSet(); + private final AmqpFieldMap _fieldMap = new AmqpFieldMap(); + + private final AmqpOrdinalVersionMap _indexMap = new AmqpOrdinalVersionMap(); + private final AmqpFlagMap _clientMethodFlagMap = new AmqpFlagMap(); // Method called on client ( in XML) + private final AmqpFlagMap _serverMethodFlagMap = new AmqpFlagMap(); // Method called on server ( in XML) + + private final Map _versionToFieldsMap = new HashMap(); + + private final Map _versionToFieldCount = new HashMap(); + + private final String _name; + private final Generator _generator; + + + public AmqpMethod(String name, Generator generator) + { + _name = name; + _generator = generator; + } + + public boolean addFromNode(Node methodNode, int ordinal, AmqpVersion version) + throws AmqpParseException, AmqpTypeMappingException + { + _versionSet.add(version); + boolean serverChassisFlag = false; + boolean clientChassisFlag = false; + int index = Utils.getNamedIntegerAttribute(methodNode, "index"); + AmqpVersionSet indexVersionSet = _indexMap.get(index); + if (indexVersionSet != null) + { + indexVersionSet.add(version); + } + else + { + indexVersionSet = new AmqpVersionSet(); + indexVersionSet.add(version); + _indexMap.put(index, indexVersionSet); + } + NodeList nList = methodNode.getChildNodes(); + AtomicInteger fieldCntr = _versionToFieldCount.get(version); + if(fieldCntr == null) + { + fieldCntr = new AtomicInteger(0); + _versionToFieldCount.put(version, fieldCntr); + } + for (int i = 0; i < nList.getLength(); i++) + { + Node child = nList.item(i); + if (child.getNodeName().compareTo(Utils.ELEMENT_FIELD) == 0) + { + String fieldName = _generator.prepareDomainName(Utils.getNamedAttribute(child, + Utils.ATTRIBUTE_NAME)); + AmqpField thisField = _fieldMap.get(fieldName); + AmqpFieldMap versionSpecificFieldMap = _versionToFieldsMap.get(version); + if (versionSpecificFieldMap == null) + { + versionSpecificFieldMap = new AmqpFieldMap(); + _versionToFieldsMap.put(version, versionSpecificFieldMap); + } + + + if (thisField == null) + { + thisField = new AmqpField(fieldName, _generator); + _fieldMap.add(fieldName, thisField); + } + + AmqpField versionSpecificField = new AmqpField(fieldName, _generator); + versionSpecificFieldMap.add(fieldName, versionSpecificField); + + versionSpecificField.addFromNode(child, fieldCntr.intValue(), version); + + if (!thisField.addFromNode(child, fieldCntr.getAndIncrement(), version)) + { + String className = _generator.prepareClassName(Utils.getNamedAttribute(methodNode.getParentNode(), + Utils.ATTRIBUTE_NAME)); + String methodName = _generator.prepareMethodName(Utils.getNamedAttribute(methodNode, + Utils.ATTRIBUTE_NAME)); + System.out.println("INFO: Generation supression tag found for field " + + className + "." + methodName + "." + fieldName + " - removing."); + thisField.removeVersion(version); + _fieldMap.remove(fieldName); + } + } + else if (child.getNodeName().compareTo(Utils.ELEMENT_CHASSIS) == 0) + { + String chassisName = Utils.getNamedAttribute(child, Utils.ATTRIBUTE_NAME); + if (chassisName.compareTo("server") == 0) + { + serverChassisFlag = true; + } + else if (chassisName.compareTo("client") == 0) + { + clientChassisFlag = true; + } + } + else if (child.getNodeName().compareTo(Utils.ELEMENT_CODEGEN) == 0) + { + String value = Utils.getNamedAttribute(child, Utils.ATTRIBUTE_VALUE); + if (value.compareTo("no-gen") == 0) + { + return false; + } + } + } + processChassisFlags(serverChassisFlag, clientChassisFlag, version); + return true; + } + + public void removeVersion(AmqpVersion version) + { + _clientMethodFlagMap.removeVersion(version); + _serverMethodFlagMap.removeVersion(version); + _indexMap.removeVersion(version); + _fieldMap.removeVersion(version); + _versionSet.remove(version); + } + + public void print(PrintStream out, int marginSize, int tabSize) + { + String margin = Utils.createSpaces(marginSize); + String tab = Utils.createSpaces(tabSize); + out.println(margin + "[M] " + _name + " {" + (_serverMethodFlagMap.isSet() ? "S " + + _serverMethodFlagMap + ( + _clientMethodFlagMap.isSet() ? ", " : "") : "") + + (_clientMethodFlagMap.isSet() + ? "C " + _clientMethodFlagMap : "") + "}" + ": " + + _versionSet); + + for (Integer thisIndex : _indexMap.keySet()) + { + AmqpVersionSet indexVersionSet = _indexMap.get(thisIndex); + out.println(margin + tab + "[I] " + thisIndex + indexVersionSet); + } + + for (String thisFieldName : _fieldMap.keySet()) + { + AmqpField thisField = _fieldMap.get(thisFieldName); + thisField.print(out, marginSize + tabSize, tabSize); + } + } + + protected void processChassisFlags(boolean serverFlag, boolean clientFlag, AmqpVersion version) + { + AmqpVersionSet versionSet = _serverMethodFlagMap.get(serverFlag); + if (versionSet != null) + { + versionSet.add(version); + } + else + { + versionSet = new AmqpVersionSet(); + versionSet.add(version); + _serverMethodFlagMap.put(serverFlag, versionSet); + } + + versionSet = _clientMethodFlagMap.get(clientFlag); + if (versionSet != null) + { + versionSet.add(version); + } + else + { + versionSet = new AmqpVersionSet(); + versionSet.add(version); + _clientMethodFlagMap.put(clientFlag, versionSet); + } + } + + public AmqpOverloadedParameterMap getOverloadedParameterLists(AmqpVersionSet globalVersionSet, + Generator generator) + throws AmqpTypeMappingException + { + AmqpOverloadedParameterMap parameterVersionMap = new AmqpOverloadedParameterMap(); + for (AmqpVersion thisVersion : globalVersionSet) + { + AmqpOrdinalFieldMap ordinalFieldMap = _fieldMap.getMapForVersion(thisVersion, true, generator); + AmqpVersionSet methodVersionSet = parameterVersionMap.get(ordinalFieldMap); + if (methodVersionSet == null) + { + methodVersionSet = new AmqpVersionSet(); + methodVersionSet.add(thisVersion); + parameterVersionMap.put(ordinalFieldMap, methodVersionSet); + } + else + { + methodVersionSet.add(thisVersion); + } + } + return parameterVersionMap; + } + + public boolean isVersionInterfaceConsistent() + { + return isVersionInterfaceConsistent(_generator.getVersionSet()); + } + + public boolean isVersionInterfaceConsistent(AmqpVersionSet globalVersionSet) + { + if (!_versionSet.equals(globalVersionSet)) + { + return false; + } + if (!_clientMethodFlagMap.isVersionConsistent(globalVersionSet)) + { + return false; + } + if (!_serverMethodFlagMap.isVersionConsistent(globalVersionSet)) + { + return false; + } + if (!_fieldMap.isVersionInterfaceConsistent(globalVersionSet)) + { + return false; + } + return true; + } + + public boolean isVersionConsistent() + { + return isVersionConsistent(_generator.getVersionSet()); + } + + + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + return isVersionInterfaceConsistent(globalVersionSet) + && _indexMap.isVersionConsistent(globalVersionSet) + && _fieldMap.isVersionConsistent(globalVersionSet); + } + + public AmqpVersionSet getVersionSet() + { + return _versionSet; + } + + public AmqpFieldMap getFieldMap() + { + return _fieldMap; + } + + public AmqpOrdinalVersionMap getIndexMap() + { + return _indexMap; + } + + public AmqpFlagMap getClientMethodFlagMap() + { + return _clientMethodFlagMap; + } + + public AmqpFlagMap getServerMethodFlagMap() + { + return _serverMethodFlagMap; + } + + public Map getVersionToFieldsMap() + { + return _versionToFieldsMap; + } + + public String getName() + { + return _name; + } + + public LanguageConverter getGenerator() + { + return _generator; + } + + public SingleVersionMethod asSingleVersionMethod(AmqpVersion version) + { + return new SingleVersionMethod(this, version, _generator); + } + + public Collection getFields() + { + return _fieldMap.values(); + } + + public boolean isCommon(AmqpField field) + { + return field.getVersionSet().equals(getVersionSet()) && field.isTypeAndNameConsistent(_generator); + } + + public boolean isConsistentServerMethod() + { + AmqpVersionSet serverVersions = _serverMethodFlagMap.get(true); + return (serverVersions != null) && serverVersions.containsAll(_generator.getVersionSet()); + } + + + public boolean isConsistentClientMethod() + { + AmqpVersionSet clientVersions = _clientMethodFlagMap.get(true); + return (clientVersions != null) && clientVersions.containsAll(_generator.getVersionSet()); + } + + public boolean isServerMethod(AmqpVersion version) + { + AmqpVersionSet serverVersions = _serverMethodFlagMap.get(true); + return (serverVersions != null) && serverVersions.contains(version); + } + + + public boolean isClientMethod(AmqpVersion version) + { + AmqpVersionSet clientVersions = _clientMethodFlagMap.get(true); + return (clientVersions != null) && clientVersions.contains(version); + } + + public boolean inAllVersions() + { + return _versionSet.containsAll(_generator.getVersionSet()); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java new file mode 100644 index 0000000000..d98dab4a39 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpMethodMap.java @@ -0,0 +1,36 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpMethodMap extends TreeMap +{ + public void removeVersion(AmqpVersion version) + { + for (String methodName : keySet()) + { + get(methodName).removeVersion(version); + } + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpModel.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpModel.java new file mode 100644 index 0000000000..45f0adb18d --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpModel.java @@ -0,0 +1,132 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Collection; + +public class AmqpModel implements Printable, NodeAware +{ + private final Generator _generator; + private final AmqpClassMap classMap = new AmqpClassMap(); + private final AmqpVersionSet _versionSet = new AmqpVersionSet(); + + private final Map _versionToClassMapMap = new HashMap(); + + public AmqpModel(Generator generator) + { + _generator = generator; + } + + public AmqpClassMap getAmqpClassMap(AmqpVersion version) + { + return _versionToClassMapMap.get(version); + } + + + public AmqpVersionSet getVersionSet() + { + return _versionSet; + } + + public boolean addFromNode(Node n, int o, AmqpVersion version) + throws AmqpParseException, AmqpTypeMappingException + { + _versionSet.add(version); + NodeList nList = n.getChildNodes(); + + AmqpClassMap versionSpecificClassMap = _versionToClassMapMap.get(version); + + if (versionSpecificClassMap == null) + { + versionSpecificClassMap = new AmqpClassMap(); + _versionToClassMapMap.put(version, versionSpecificClassMap); + } + + int eCntr = 0; + for (int i = 0; i < nList.getLength(); i++) + { + Node c = nList.item(i); + if (c.getNodeName().compareTo(Utils.ELEMENT_CLASS) == 0) + { + String className = _generator.prepareClassName(Utils.getNamedAttribute(c, Utils.ATTRIBUTE_NAME)); + AmqpClass thisClass = classMap.get(className); + if (thisClass == null) + { + thisClass = new AmqpClass(className, _generator); + classMap.put(className, thisClass); + } + + AmqpClass versionSpecificClass = new AmqpClass(className, _generator); + versionSpecificClassMap.put(className, versionSpecificClass); + + versionSpecificClass.addFromNode(c, eCntr, version); + + if (!thisClass.addFromNode(c, eCntr++, version)) + { + System.out.println("INFO: Generation supression tag found for class " + className + " - removing."); + thisClass.removeVersion(version); + classMap.remove(className); + } + } + } + return true; + } + + public void print(PrintStream out, int marginSize, int tabSize) + { + out.println(Utils.createSpaces(marginSize) + + "[C]=class; [M]=method; [F]=field; [D]=domain; [I]=index; [O]=ordinal" + Utils.LINE_SEPARATOR); + out.println(Utils.createSpaces(marginSize) + "Model:"); + + for (String thisClassName : classMap.keySet()) + { + AmqpClass thisClass = classMap.get(thisClassName); + thisClass.print(out, marginSize + tabSize, tabSize); + } + } + + public LanguageConverter getGenerator() + { + return _generator; + } + + public AmqpClassMap getClassMap() + { + return classMap; + } + + + public Collection getClasses() + { + return classMap.values(); + } + + public SingleVersionModel asSingleVersionModel() + { + return new SingleVersionModel(this, getVersionSet().first(), _generator); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java new file mode 100644 index 0000000000..0633eff1e1 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpOrdinalFieldMap.java @@ -0,0 +1,96 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.Iterator; +import java.util.Set; +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpOrdinalFieldMap extends TreeMap implements Comparable +{ + + + public int compareTo(Object obj) + { + AmqpOrdinalFieldMap o = (AmqpOrdinalFieldMap) obj; + Set thisKeySet = keySet(); + Set oKeySet = o.keySet(); + if (!thisKeySet.equals(oKeySet)) // Not equal, but why? + { + // Size difference + int sizeDiff = thisKeySet.size() - oKeySet.size(); // -ve if this < other + if (sizeDiff != 0) + { + return sizeDiff; + } + // Conetent difference + Iterator itr = thisKeySet.iterator(); + Iterator oItr = oKeySet.iterator(); + while (itr.hasNext() && oItr.hasNext()) + { + int diff = itr.next() - oItr.next(); // -ve if this < other + if (diff != 0) + { + return diff; + } + } + // We should never get here... + System.err.println("AmqpOrdinalFieldMap.compareTo(): " + + "WARNING - unable to find cause of keySet difference."); + } + // Keys are equal, now check the String[]s + Iterator itr = thisKeySet.iterator(); + Iterator oItr = oKeySet.iterator(); + while (itr.hasNext() && oItr.hasNext()) + { + String[] thisPair = get(itr.next()); + String[] oPair = o.get(oItr.next()); + // Size difference + int sizeDiff = thisPair.length - oPair.length; // -ve if this < other + if (sizeDiff != 0) + { + return sizeDiff; + } + // Conetent difference + for (int i = 0; i < thisPair.length; i++) + { + int diff = thisPair[i].compareTo(oPair[i]); + if (diff != 0) + { + return diff; + } + } + } + return 0; + } + + public String toString() + { + StringBuffer sb = new StringBuffer(); + for (Integer thisOrdinal : keySet()) + { + String[] pair = get(thisOrdinal); + sb.append("[" + thisOrdinal + "] " + pair[0] + " : " + pair[1] + Utils.LINE_SEPARATOR); + } + return sb.toString(); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java new file mode 100644 index 0000000000..fede88631a --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpOrdinalVersionMap.java @@ -0,0 +1,76 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.ArrayList; +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpOrdinalVersionMap extends TreeMap implements VersionConsistencyCheck +{ + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet) + { + if (size() != 1) + { + return false; + } + return get(firstKey()).equals(globalVersionSet); + } + + public int getOrdinal(AmqpVersion version) + throws AmqpTypeMappingException + { + for (Integer thisOrdinal : keySet()) + { + AmqpVersionSet versionSet = get(thisOrdinal); + if (versionSet.contains(version)) + { + return thisOrdinal; + } + } + throw new AmqpTypeMappingException("Unable to locate version " + version + " in ordianl version map."); + } + + public boolean removeVersion(AmqpVersion version) + { + Boolean res = false; + ArrayList removeList = new ArrayList(); + for (Integer ordinal : keySet()) + { + AmqpVersionSet versionSet = get(ordinal); + if (versionSet.contains(version)) + { + versionSet.remove(version); + if (versionSet.isEmpty()) + { + removeList.add(ordinal); + } + res = true; + } + } + // Get rid of ordinals no longer in use + for (Integer ordinal : removeList) + { + remove(ordinal); + } + return res; + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java new file mode 100644 index 0000000000..10978d0e4a --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpOverloadedParameterMap.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.TreeMap; + +@SuppressWarnings("serial") +public class AmqpOverloadedParameterMap extends TreeMap +{ + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpParseException.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpParseException.java new file mode 100644 index 0000000000..3f3d4611fc --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpParseException.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +@SuppressWarnings("serial") +public class AmqpParseException extends RuntimeException +{ + public AmqpParseException(String msg) + { + super(msg); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpTemplateException.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpTemplateException.java new file mode 100644 index 0000000000..1ac09ea453 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpTemplateException.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +@SuppressWarnings("serial") +public class AmqpTemplateException extends RuntimeException +{ + public AmqpTemplateException(String msg) + { + super(msg); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java new file mode 100644 index 0000000000..127a8835b0 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpTypeMappingException.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +@SuppressWarnings("serial") +public class AmqpTypeMappingException extends RuntimeException +{ + public AmqpTypeMappingException(String msg) + { + super(msg); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpVersion.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpVersion.java new file mode 100644 index 0000000000..dbeef1b895 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpVersion.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.gentools; + +public class AmqpVersion implements Comparable +{ + private final int _major; + private final int _minor; + + public AmqpVersion(int major, int minor) + { + _major = major; + _minor = minor; + } + + public AmqpVersion(AmqpVersion version) + { + _major = version.getMajor(); + _minor = version.getMinor(); + } + + public int getMajor() + { + return _major; + } + + public int getMinor() + { + return _minor; + } + + public int compareTo(AmqpVersion v) + { + if (_major != v.getMajor()) + { + return _major - v.getMajor(); + } + if (_minor != v.getMinor()) + { + return _minor - v.getMinor(); + } + return 0; + } + + public String namespace() + { + return "ver_" + _major + "_" + _minor; + } + + public String toString() + { + return _major + "-" + _minor; + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java b/java/common/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java new file mode 100644 index 0000000000..6419e23a1e --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/AmqpVersionSet.java @@ -0,0 +1,79 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.io.PrintStream; +import java.util.Iterator; +import java.util.TreeSet; + +@SuppressWarnings("serial") +public class AmqpVersionSet extends TreeSet implements Printable, Comparable +{ + public AmqpVersionSet() + { + super(); + } + + public AmqpVersionSet(AmqpVersion version) + { + super(); + add(version); + } + + public AmqpVersion find(AmqpVersion version) + { + for (AmqpVersion v : this) + { + if (v.compareTo(version) == 0) + { + return v; + } + } + return null; + } + + public void print(PrintStream out, int marginSize, int tabSize) + { + out.print(Utils.createSpaces(marginSize) + "Version Set: " + toString() + Utils.LINE_SEPARATOR); + } + + public int compareTo(AmqpVersionSet other) + { + int res = size() - other.size(); + if (res != 0) + { + return res; + } + Iterator vItr = iterator(); + Iterator oItr = other.iterator(); + while (vItr.hasNext() && oItr.hasNext()) + { + AmqpVersion version = vItr.next(); + AmqpVersion oVersion = oItr.next(); + res = version.compareTo(oVersion); + if (res != 0) + { + return res; + } + } + return 0; + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/BitFieldGenerateMethod.java b/java/common/gentools/src/org/apache/qpid/gentools/BitFieldGenerateMethod.java new file mode 100644 index 0000000000..d85510ee98 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/BitFieldGenerateMethod.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + + +import java.util.List; + +public interface BitFieldGenerateMethod +{ + String generate(List bitFieldList, int ordinal, int indentSize, int tabSize); +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/CommandGenerateMethod.java b/java/common/gentools/src/org/apache/qpid/gentools/CommandGenerateMethod.java new file mode 100644 index 0000000000..641f50c3f8 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/CommandGenerateMethod.java @@ -0,0 +1,26 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +public interface CommandGenerateMethod +{ + String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast); +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/ConsolidatedField.java b/java/common/gentools/src/org/apache/qpid/gentools/ConsolidatedField.java new file mode 100644 index 0000000000..9ab7eb178b --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/ConsolidatedField.java @@ -0,0 +1,120 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.List; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +/** + * Created by IntelliJ IDEA. + * User: U146758 + * Date: 06-Mar-2007 + * Time: 09:22:21 + * To change this template use File | Settings | File Templates. + */ +public class ConsolidatedField +{ + private final String _name; + private final String _type; + private final List _underlyingFields = new ArrayList(); + private final Generator _generator; + private boolean _isConsolidated; + + public ConsolidatedField(Generator generator, String name, String type) + { + this(generator,name,type,name,false); + } + + public ConsolidatedField(Generator generator, String name, String type, String firstField) + { + this(generator,name,type,firstField,true); + } + + public ConsolidatedField(Generator generator, String name, String type, String firstField, boolean consolidated) + { + + _generator = generator; + _name = name; + _type = type; + _isConsolidated = consolidated; + _underlyingFields.add(firstField); + + } + + + public void setConsolidated(boolean consolidated) + { + _isConsolidated = consolidated; + } + + public String getName() + { + return _name; + } + + public String getType() + { + return _type; + } + + public String getNativeType() + { + return _generator.getNativeType(_type); + } + + public String getEncodingType() + { + return _generator.getEncodingType(_type); + } + + public void add(String name) + { + _underlyingFields.add(name); + } + + public Collection getUnderlyingFields() + { + return Collections.unmodifiableCollection(_underlyingFields); + } + + public int getPosition(String fieldName) + { + return _underlyingFields.indexOf(fieldName); + } + + public boolean isConsolidated() + { + return _isConsolidated; + } + + public boolean isFixedSize() + { + return _generator.isFixedSizeType( getType() ); + } + + public int getSize() + { + return _generator.getTypeSize( getType() ); + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/CppGenerator.java b/java/common/gentools/src/org/apache/qpid/gentools/CppGenerator.java new file mode 100644 index 0000000000..4f58cba34e --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/CppGenerator.java @@ -0,0 +1,1716 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.TreeMap; + +public class CppGenerator extends Generator +{ + protected static final String versionNamespaceStartToken = "${version_namespace_start}"; + protected static final String versionNamespaceEndToken = "${version_namespace_end}"; + + // TODO: Move this to parent class + protected static final int FIELD_NAME = 0; + protected static final int FIELD_CODE_TYPE = 1; + + /** + * A complete list of C++ reserved words. The names of varous XML elements within the AMQP + * specification file are used for C++ identifier names in the generated code. Each proposed + * name is checked against this list and is modified (by adding an '_' to the end of the + * name - see function parseForReservedWords()) if found to be present. + */ + protected static final String[] cppReservedWords = {"and", "and_eq", "asm", "auto", "bitand", + "bitor", "bool", "break", "case", "catch", "char", "class", "compl", "const", "const_cast", + "continue", "default", "delete", "do", "DomainInfo", "double", "dynamic_cast", "else", + "enum", "explicit", "extern", "false", "float", "for", "friend", "goto", "if", "inline", + "int", "long", "mutable", "namespace", "new", "not", "not_eq", "operator", "or", "or_eq", + "private", "protected", "public", "register", "reinterpret_cast", "return", "short", + "signed", "sizeof", "static", "static_cast", "struct", "switch", "template", "this", + "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned", "using", + "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq"}; + + /** + * Although not reserved words, the following list of variable names that may cause compile + * problems within a C++ environment because they clash with common #includes. The names of + * varous XML elements within the AMQP specification file are used for C++ identifier names + * in the generated code. Each proposed name is checked against this list and is modified + * (by adding an '_' to the end of the name - see function parseForReservedWords()) if found + * to be present. This list is best added to on an as-needed basis. + */ + protected static final String[] cppCommonDefines = {"string"}; + + // TODO: Move this to the Generator superclass? + protected boolean quietFlag; // Supress warning messages to the console + + private class DomainInfo + { + public String type; + public String size; + public String encodeExpression; + public String decodeExpression; + + public DomainInfo(String domain, String size, String encodeExpression, + String decodeExpression) + { + this.type = domain; + this.size = size; + this.encodeExpression = encodeExpression; + this.decodeExpression = decodeExpression; + } + } + + private static TreeMap typeMap = new TreeMap(); + + public CppGenerator() + { + super(); + quietFlag = true; + // Load C++ type and size maps. + // Adjust or add to these lists as new types are added/defined. + // The char '#' will be replaced by the field variable name (any type). + // The char '~' will be replaced by the compacted bit array size (type bit only). + typeMap.put("bit", new DomainInfo( + "bool", // type + "~", // size + "", // encodeExpression + "")); // decodeExpression + typeMap.put("content", new DomainInfo( + "Content", // type + "#.size()", // size + "buffer.putContent(#)", // encodeExpression + "buffer.getContent(#)")); // decodeExpression + typeMap.put("long", new DomainInfo( + "u_int32_t", // type + "4", // size + "buffer.putLong(#)", // encodeExpression + "# = buffer.getLong()")); // decodeExpression + typeMap.put("longlong", new DomainInfo( + "u_int64_t", // type + "8", // size + "buffer.putLongLong(#)", // encodeExpression + "# = buffer.getLongLong()")); // decodeExpression + typeMap.put("longstr", new DomainInfo( + "string", // type + "4 + #.length()", // size + "buffer.putLongString(#)", // encodeExpression + "buffer.getLongString(#)")); // decodeExpression + typeMap.put("octet", new DomainInfo( + "u_int8_t", // type + "1", // size + "buffer.putOctet(#)", // encodeExpression + "# = buffer.getOctet()")); // decodeExpression + typeMap.put("short", new DomainInfo( + "u_int16_t", // type + "2", // size + "buffer.putShort(#)", // encodeExpression + "# = buffer.getShort()")); // decodeExpression + typeMap.put("shortstr", new DomainInfo( + "string", // type + "1 + #.length()", // size + "buffer.putShortString(#)", // encodeExpression + "buffer.getShortString(#)")); // decodeExpression + typeMap.put("table", new DomainInfo( + "FieldTable", // type + "#.size()", // size + "buffer.putFieldTable(#)", // encodeExpression + "buffer.getFieldTable(#)")); // decodeExpression + typeMap.put("timestamp", new DomainInfo( + "u_int64_t", // type + "8", // size + "buffer.putLongLong(#)", // encodeExpression + "buffer.getLongLong(#)")); // decodeExpression + } + + + public boolean isQuietFlag() + { + return quietFlag; + } + + public void setQuietFlag(boolean quietFlag) + { + this.quietFlag = quietFlag; + } + + // === Start of methods for Interface LanguageConverter === + + public String prepareClassName(String className) + { + return camelCaseName(className, true); + } + + public String prepareMethodName(String methodName) + { + return camelCaseName(methodName, false); + } + + public String prepareDomainName(String domainName) + { + return camelCaseName(domainName, false); + } + + + public String getGeneratedType(String domainName, AmqpVersion version) + throws AmqpTypeMappingException + { + String domainType = getDomainType(domainName, version); + if (domainType == null) + { + throw new AmqpTypeMappingException("Domain type \"" + domainName + + "\" not found in C++ typemap."); + } + DomainInfo info = typeMap.get(domainType); + if (info == null) + { + throw new AmqpTypeMappingException("Unknown domain: \"" + domainType + "\""); + } + return info.type; + } + + // === Abstract methods from class Generator - C++-specific implementation === + + @Override + protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method, + AmqpField field, AmqpVersion version) + { + StringBuffer sb = new StringBuffer(filenameTemplate); + if (thisClass != null) + { + replaceToken(sb, "${CLASS}", thisClass.getName()); + } + if (method != null) + { + replaceToken(sb, "${METHOD}", method.getName()); + } + if (field != null) + { + replaceToken(sb, "${FIELD}", field.getName()); + } + return sb.toString(); + } + + @Override + protected void processModelTemplate(NamedTemplate template) + { + processTemplate(template, null, null, null, null); + } + + @Override + protected void processClassTemplate(NamedTemplate template, AmqpClass thisClass) + { + processTemplate(template, thisClass, null, null, null); + } + + @Override + protected void processMethodTemplate(NamedTemplate template, AmqpClass thisClass, + AmqpMethod method) + { + StringBuffer sb = new StringBuffer(template.getTemplate()); + String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, null, null); + boolean templateProcessedFlag = false; + + // If method is not version consistent, create a namespace for each version + // i.e. copy the bit between the versionNamespaceStartToken and versionNamespaceEndToken + // once for each namespace. + if (method != null) + { + if (!method.isVersionConsistent(getVersionSet())) + { + int namespaceStartIndex = sb.indexOf(versionNamespaceStartToken); + int namespaceEndIndex = sb.indexOf(versionNamespaceEndToken) + + versionNamespaceEndToken.length(); + if (namespaceStartIndex >= 0 && namespaceEndIndex >= 0 && + namespaceStartIndex <= namespaceEndIndex) + { + String namespaceSpan = sb.substring(namespaceStartIndex, namespaceEndIndex) + CR; + sb.delete(namespaceStartIndex, namespaceEndIndex); + for (AmqpVersion v : method.getVersionSet()) + { + StringBuffer nssb = new StringBuffer(namespaceSpan); + processTemplate(nssb, thisClass, method, null, template.getName(), v); + sb.insert(namespaceStartIndex, nssb); + } + // Process all tokens *not* within the namespace span prior to inserting namespaces + processTemplate(sb, thisClass, method, null, template.getName(), null); + } + templateProcessedFlag = true; + } + } + // Remove any remaining namespace tags + int nsTokenIndex = sb.indexOf(versionNamespaceStartToken); + while (nsTokenIndex > 0) + { + sb.delete(nsTokenIndex, nsTokenIndex + versionNamespaceStartToken.length()); + nsTokenIndex = sb.indexOf(versionNamespaceStartToken); + } + nsTokenIndex = sb.indexOf(versionNamespaceEndToken); + while (nsTokenIndex > 0) + { + sb.delete(nsTokenIndex, nsTokenIndex + versionNamespaceEndToken.length()); + nsTokenIndex = sb.indexOf(versionNamespaceEndToken); + } + + if (!templateProcessedFlag) + { + processTemplate(sb, thisClass, method, null, template.getName(), null); + } + writeTargetFile(sb, new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename)); + generatedFileCounter++; + } + + @Override + protected void processTemplate(NamedTemplate template, AmqpClass thisClass, AmqpMethod method, + AmqpField field, AmqpVersion version) + { + StringBuffer sb = new StringBuffer(template.getTemplate()); + String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, field, version); + processTemplate(sb, thisClass, method, field, template.getName(), null); + writeTargetFile(sb, new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename)); + generatedFileCounter++; + } + + protected void processTemplate(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, + AmqpField field, String templateFileName, AmqpVersion version) + { + try + { + processAllLists(sb, thisClass, method, version); + } + catch (AmqpTemplateException e) + { + System.out.println("ERROR: " + templateFileName + ": " + e.getMessage()); + } + try + { + processAllTokens(sb, thisClass, method, field, version); + } + catch (AmqpTemplateException e) + { + System.out.println("ERROR: " + templateFileName + ": " + e.getMessage()); + } + } + + @Override + protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, AmqpField field, + AmqpVersion version) + { + if (token.compareTo("${GENERATOR}") == 0) + { + return GENERATOR_INFO; + } + if (token.compareTo("${CLASS}") == 0 && thisClass != null) + { + return thisClass.getName(); + } + if (token.compareTo("${CLASS_ID_INIT}") == 0 && thisClass != null) + { + if (version == null) + { + return String.valueOf(thisClass.getIndexMap().firstKey()); + } + return getIndex(thisClass.getIndexMap(), version); + } + if (token.compareTo("${METHOD}") == 0 && method != null) + { + return method.getName(); + } + if (token.compareTo("${METHOD_ID_INIT}") == 0 && method != null) + { + if (version == null) + { + return String.valueOf(method.getIndexMap().firstKey()); + } + return getIndex(method.getIndexMap(), version); + } + if (token.compareTo("${FIELD}") == 0 && field != null) + { + return field.getName(); + } + if (token.compareTo(versionNamespaceStartToken) == 0 && version != null) + { + return "namespace " + version.namespace() + CR + "{"; + } + if (token.compareTo(versionNamespaceEndToken) == 0 && version != null) + { + return "} // namespace " + version.namespace(); + } + if (token.compareTo("${mb_constructor_with_initializers}") == 0) + { + return generateConstructor(thisClass, method, version, 4, 4); + } + if (token.compareTo("${mb_server_operation_invoke}") == 0) + { + return generateServerOperationsInvoke(thisClass, method, version, 4, 4); + } + if (token.compareTo("${mb_buffer_param}") == 0) + { + return method.getFieldMap().size() > 0 ? " buffer" : ""; + } + if (token.compareTo("${hv_latest_major}") == 0) + { + return String.valueOf(getVersionSet().last().getMajor()); + } + if (token.compareTo("${hv_latest_minor}") == 0) + { + return String.valueOf(getVersionSet().last().getMinor()); + } + + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + + @Override + protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpModel model, AmqpVersion version) + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokxStart = tline.indexOf('$'); + String token = tline.substring(tokxStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + // ClientOperations.h + if (token.compareTo("${coh_method_handler_get_method}") == 0) + { + codeSnippet = generateOpsMethodHandlerGetMethods(model, false, 4); + } + else if (token.compareTo("${coh_inner_class}") == 0) + { + codeSnippet = generateOpsInnerClasses(model, false, 4, 4); + } + + // ServerOperations.h + else if (token.compareTo("${soh_method_handler_get_method}") == 0) + { + codeSnippet = generateOpsMethodHandlerGetMethods(model, true, 4); + } + else if (token.compareTo("${soh_inner_class}") == 0) + { + codeSnippet = generateOpsInnerClasses(model, true, 4, 4); + } + + // ClientProxy.h/cpp + else if (token.compareTo("${cph_inner_class_instance}") == 0) + { + codeSnippet = generateProxyInnerClassInstances(model, false, 4); + } + else if (token.compareTo("${cph_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodDecls(model, false, 4); + } + else if (token.compareTo("${cph_inner_class_defn}") == 0) + { + codeSnippet = generateProxyInnerClassDefinitions(model, false, 4, 4); + } + else if (token.compareTo("${cpc_constructor_initializer}") == 0) + { + codeSnippet = generateProxyConstructorInitializers(model, false, 4); + } + else if (token.compareTo("${cpc_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodImpls(model, false, 0, 4); + } + else if (token.compareTo("${cpc_inner_class_impl}") == 0) + { + codeSnippet = generateProxyInnerClassImpl(model, false, 0, 4); + } + else if (token.compareTo("${cph_handler_pointer_defn}") == 0) + { + codeSnippet = generateHandlerPointerDefinitions(model, false, 4); + } + else if (token.compareTo("${cph_handler_pointer_get_method}") == 0) + { + codeSnippet = generateHandlerPointerGetMethods(model, false, 4); + } + + // SerrverProxy.h/cpp + else if (token.compareTo("${sph_inner_class_instance}") == 0) + { + codeSnippet = generateProxyInnerClassInstances(model, true, 4); + } + else if (token.compareTo("${sph_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodDecls(model, true, 4); + } + else if (token.compareTo("${sph_inner_class_defn}") == 0) + { + codeSnippet = generateProxyInnerClassDefinitions(model, true, 4, 4); + } + else if (token.compareTo("${spc_constructor_initializer}") == 0) + { + codeSnippet = generateProxyConstructorInitializers(model, true, 4); + } + else if (token.compareTo("${spc_inner_class_get_method}") == 0) + { + codeSnippet = generateProxyInnerClassGetMethodImpls(model, true, 0, 4); + } + else if (token.compareTo("${spc_inner_class_impl}") == 0) + { + codeSnippet = generateProxyInnerClassImpl(model, true, 0, 4); + } + else if (token.compareTo("${sph_handler_pointer_defn}") == 0) + { + codeSnippet = generateHandlerPointerDefinitions(model, true, 4); + } + else if (token.compareTo("${sph_handler_pointer_get_method}") == 0) + { + codeSnippet = generateHandlerPointerGetMethods(model, true, 4); + } + + // amqp_methods.h/cpp + else if (token.compareTo("${mh_method_body_class_indlude}") == 0) + { + codeSnippet = generateMethodBodyIncludeList(model, 0); + } + else if (token.compareTo("${mh_method_body_class_instance}") == 0) + { + codeSnippet = generateMethodBodyInstances(model, 0); + } + else if (token.compareTo("${mc_create_method_body_map_entry}") == 0) + { + codeSnippet = generateMethodBodyMapEntry(model, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token \"" + token + "\" unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpClass thisClass) + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokxStart = tline.indexOf('$'); + String token = tline.substring(tokxStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${cpc_method_body_include}") == 0) + { + codeSnippet = generateMethodBodyIncludes(thisClass, 0); + } + else if (token.compareTo("${spc_method_body_include}") == 0) + { + codeSnippet = generateMethodBodyIncludes(thisClass, 0); + } + else if (token.compareTo("${mc_method_body_include}") == 0) + { + codeSnippet = generateMethodBodyIncludes(thisClass, 0); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpFieldMap fieldMap, AmqpVersion version) + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokxStart = tline.indexOf('$'); + String token = tline.substring(tokxStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${mb_field_declaration}") == 0) + { + codeSnippet = generateFieldDeclarations(fieldMap, version, 4); + } + else if (token.compareTo("${mb_field_get_method}") == 0) + { + codeSnippet = generateFieldGetMethods(fieldMap, version, 4); + } + else if (token.compareTo("${mb_field_print}") == 0) + { + codeSnippet = generatePrintMethodContents(fieldMap, version, 8); + } + else if (token.compareTo("${mb_body_size}") == 0) + { + codeSnippet = generateBodySizeMethodContents(fieldMap, version, 8); + } + else if (token.compareTo("${mb_encode}") == 0) + { + codeSnippet = generateEncodeMethodContents(fieldMap, version, 8); + } + else if (token.compareTo("${mb_decode}") == 0) + { + codeSnippet = generateDecodeMethodContents(fieldMap, version, 8); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet) + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokxStart = tline.indexOf('$'); + String token = tline.substring(tokxStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${ch_get_value_method}") == 0) + { + codeSnippet = generateConstantGetMethods(constantSet, 4, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + // === Protected and private helper functions unique to C++ implementation === + + // Methods for generation of code snippets for AMQP_Constants.h file + + protected String generateConstantGetMethods(AmqpConstantSet constantSet, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + for (AmqpConstant thisConstant : constantSet.getContstants()) + { + if (thisConstant.isVersionConsistent(getVersionSet())) + { + // return a constant + String value = thisConstant.firstKey(); + sb.append(indent + "static const char* " + thisConstant.getName() + "() { return \"" + + thisConstant.firstKey() + "\"; }" + CR); + if (Utils.containsOnlyDigits(value)) + { + sb.append(indent + "static int " + thisConstant.getName() + "AsInt() { return " + + thisConstant.firstKey() + "; }" + CR); + } + if (Utils.containsOnlyDigitsAndDecimal(value)) + { + sb.append(indent + "static double " + thisConstant.getName() + "AsDouble() { return (double)" + + thisConstant.firstKey() + "; }" + CR); + } + sb.append(CR); + } + else + { + // Return version-specific constant + sb.append(generateVersionDependentGet(thisConstant, "const char*", "", "\"", "\"", indentSize, tabSize)); + sb.append(generateVersionDependentGet(thisConstant, "int", "AsInt", "", "", indentSize, tabSize)); + sb.append(generateVersionDependentGet(thisConstant, "double", "AsDouble", "(double)", "", indentSize, tabSize)); + sb.append(CR); + } + } + return sb.toString(); + } + + protected String generateVersionDependentGet(AmqpConstant constant, String methodReturnType, + String methodNameSuffix, String returnPrefix, String returnPostfix, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + methodReturnType + " " + constant.getName() + methodNameSuffix + + "() const" + CR); + sb.append(indent + "{" + CR); + boolean first = true; + for (String thisValue : constant.keySet()) + { + AmqpVersionSet versionSet = constant.get(thisValue); + sb.append(indent + tab + (first ? "" : "else ") + "if (" + generateVersionCheck(versionSet) + + ")" + CR); + sb.append(indent + tab + "{" + CR); + if (methodReturnType.compareTo("int") == 0 && !Utils.containsOnlyDigits(thisValue)) + { + sb.append(generateConstantDeclarationException(constant.getName(), methodReturnType, + indentSize + (2 * tabSize), tabSize)); + } + else if (methodReturnType.compareTo("double") == 0 && !Utils.containsOnlyDigitsAndDecimal(thisValue)) + { + sb.append(generateConstantDeclarationException(constant.getName(), methodReturnType, + indentSize + (2 * tabSize), tabSize)); + } + else + { + sb.append(indent + tab + tab + "return " + returnPrefix + thisValue + returnPostfix + ";" + CR); + } + sb.append(indent + tab + "}" + CR); + first = false; + } + sb.append(indent + tab + "else" + CR); + sb.append(indent + tab + "{" + CR); + sb.append(indent + tab + tab + "std::stringstream ss;" + CR); + sb.append(indent + tab + tab + "ss << \"Constant \\\"" + constant.getName() + + "\\\" is undefined for AMQP version \" <<" + CR); + sb.append(indent + tab + tab + tab + "version.toString() << \".\";" + CR); + sb.append(indent + tab + tab + "throw ProtocolVersionException(ss.str());" + CR); + sb.append(indent + tab + "}" + CR); + sb.append(indent + "}" + CR); + return sb.toString(); + } + + protected String generateConstantDeclarationException(String name, String methodReturnType, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "std::stringstream ss;" + CR); + sb.append(indent + "ss << \"Constant \\\"" + name + "\\\" cannot be converted to type " + + methodReturnType + " for AMQP version \" <<" + CR); + sb.append(indent + tab + "version.toString() << \".\";" + CR); + sb.append(indent + "throw ProtocolVersionException(ss.str());" + CR); + return sb.toString(); + } + + // Methods used for generation of code snippets for Server/ClientOperations class generation + + protected String generateOpsMethodHandlerGetMethods(AmqpModel model, boolean serverFlag, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + // Only generate for this class if there is at least one method of the + // required chassis (server/client flag). + boolean chassisFoundFlag = false; + for (String thisMethodName : thisClass.getMethodMap().keySet()) + { + AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); + boolean clientChassisFlag = method.getClientMethodFlagMap().isSet(); + boolean serverChassisFlag = method.getServerMethodFlagMap().isSet(); + if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) + { + chassisFoundFlag = true; + } + } + if (chassisFoundFlag) + { + sb.append(indent + "virtual AMQP_" + (serverFlag ? "Server" : "Client") + "Operations::" + + thisClass.getName() + "Handler* get" + thisClass.getName() + "Handler() = 0;" + CR); + } + } + return sb.toString(); + } + + protected String generateOpsInnerClasses(AmqpModel model, boolean serverFlag, int indentSize, int tabSize) + { + + String proxyClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + boolean first = true; + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + String handlerClassName = thisClass.getName() + "Handler"; + if (!first) + { + sb.append(CR); + } + sb.append(indent + "// ==================== class " + handlerClassName + + " ====================" + CR); + sb.append(indent + "class " + handlerClassName); + if (thisClass.getVersionSet().size() != getVersionSet().size()) + { + sb.append(" // AMQP Version(s) " + thisClass.getVersionSet() + CR); + } + else + { + sb.append(CR); + } + sb.append(indent + "{" + CR); + sb.append(indent + "private:" + CR); + sb.append(indent + tab + proxyClassName + "* parent;" + CR); + sb.append(CR); + sb.append(indent + tab + "// Constructors and destructors" + CR); + sb.append(CR); + sb.append(indent + "protected:" + CR); + sb.append(indent + tab + handlerClassName + "() {}" + CR); + sb.append(indent + "public:" + CR); + sb.append(indent + tab + handlerClassName + + "(" + proxyClassName + "* _parent) {parent = _parent;}" + CR); + sb.append(indent + tab + "virtual ~" + handlerClassName + "() {}" + CR); + sb.append(CR); + sb.append(indent + tab + "// Protocol methods" + CR); + sb.append(CR); + sb.append(generateInnerClassMethods(thisClass, serverFlag, true, indentSize + tabSize, tabSize)); + sb.append(indent + "}; // class " + handlerClassName + CR); + first = false; + } + return sb.toString(); + } + + protected String generateInnerClassMethods(AmqpClass thisClass, boolean serverFlag, + boolean abstractMethodFlag, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + (abstractMethodFlag ? "Operations" + : "Proxy"); + boolean first = true; + for (String thisMethodName : thisClass.getMethodMap().keySet()) + { + AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); + boolean clientChassisFlag = method.getClientMethodFlagMap().isSet(); + boolean serverChassisFlag = method.getServerMethodFlagMap().isSet(); + if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) + { + String methodName = parseForReservedWords(method.getName(), outerClassName + "." + thisClass.getName()); + AmqpOverloadedParameterMap overloadededParameterMap = + method.getOverloadedParameterLists(thisClass.getVersionSet(), this); + for (AmqpOrdinalFieldMap thisFieldMap : overloadededParameterMap.keySet()) + { + AmqpVersionSet versionSet = overloadededParameterMap.get(thisFieldMap); + if (!first) + { + sb.append(CR); + } + sb.append(indent + "virtual void " + methodName + "( u_int16_t channel"); + sb.append(generateMethodParameterList(thisFieldMap, indentSize + (5 * tabSize), true, true, true)); + sb.append(" )"); + if (abstractMethodFlag) + { + sb.append(" = 0"); + } + sb.append(";"); + if (versionSet.size() != getVersionSet().size()) + { + sb.append(" // AMQP Version(s) " + versionSet); + } + sb.append(CR); + first = false; + } + } + } + return sb.toString(); + } + + // Methods used for generation of code snippets for Server/ClientProxy class generation + + protected String generateHandlerPointerDefinitions(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations"; + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + sb.append(indent + outerClassName + "::" + thisClass.getName() + "Handler* " + + thisClass.getName() + "HandlerPtr;" + CR); + } + return sb.toString(); + } + + protected String generateHandlerPointerGetMethods(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations"; + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + sb.append(indent + "virtual inline " + outerClassName + "::" + thisClass.getName() + "Handler* get" + + thisClass.getName() + "Handler() { return &" + Utils.firstLower(thisClass.getName()) + ";}" + CR); + } + return sb.toString(); + } + + protected String generateProxyInnerClassInstances(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + String instanceName = parseForReservedWords(Utils.firstLower(thisClass.getName()), outerClassName); + String className = parseForReservedWords(thisClass.getName(), null); + sb.append(indent + className + " " + instanceName + ";"); + if (thisClass.getVersionSet().size() != getVersionSet().size()) + { + sb.append(" // AMQP Version(s) " + thisClass.getVersionSet() + CR); + } + else + { + sb.append(CR); + } + } + return sb.toString(); + } + + protected String generateProxyInnerClassGetMethodDecls(AmqpModel model, boolean serverFlag, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + String className = parseForReservedWords(thisClass.getName(), outerClassName); + sb.append(indent + className + "& get" + className + "();"); + if (thisClass.getVersionSet().size() != getVersionSet().size()) + { + sb.append(" // AMQP Version(s) " + thisClass.getVersionSet() + CR); + } + else + { + sb.append(CR); + } + } + return sb.toString(); + } + + protected String generateProxyInnerClassDefinitions(AmqpModel model, boolean serverFlag, + int indentSize, int tabSize) + { + String proxyClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + boolean first = true; + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + String className = thisClass.getName(); + String superclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations::" + + thisClass.getName() + "Handler"; + if (!first) + { + sb.append(CR); + } + sb.append(indent + "// ==================== class " + className + + " ====================" + CR); + sb.append(indent + "class " + className + " : virtual public " + superclassName); + if (thisClass.getVersionSet().size() != getVersionSet().size()) + { + sb.append(" // AMQP Version(s) " + thisClass.getVersionSet() + CR); + } + else + { + sb.append(CR); + } + sb.append(indent + "{" + CR); + sb.append(indent + "private:" + CR); + sb.append(indent + tab + "OutputHandler* out;" + CR); + sb.append(indent + tab + proxyClassName + "* parent;" + CR); + sb.append(CR); + sb.append(indent + "public:" + CR); + sb.append(indent + tab + "// Constructors and destructors" + CR); + sb.append(CR); + sb.append(indent + tab + className + "(OutputHandler* out, " + proxyClassName + "* _parent) : " + CR); + sb.append(indent + tab + tab + "out(out) {parent = _parent;}" + CR); + sb.append(indent + tab + "virtual ~" + className + "() {}" + CR); + sb.append(CR); + sb.append(indent + tab + "// Protocol methods" + CR); + sb.append(CR); + sb.append(generateInnerClassMethods(thisClass, serverFlag, false, indentSize + tabSize, tabSize)); + sb.append(indent + "}; // class " + className + CR); + first = false; + } + return sb.toString(); + } + + protected String generateProxyConstructorInitializers(AmqpModel model, boolean serverFlag, + int indentSize) + { + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + String superclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Operations"; + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(indent + superclassName + "(major, minor)," + CR); + sb.append(indent + "version(major, minor)," + CR); + sb.append(indent + "out(out)"); + Iterator cItr = model.getClassMap().keySet().iterator(); + while (cItr.hasNext()) + { + AmqpClass thisClass = model.getClassMap().get(cItr.next()); + String instanceName = parseForReservedWords(Utils.firstLower(thisClass.getName()), outerClassName); + sb.append("," + CR); + sb.append(indent + instanceName + "(out, this)"); + if (!cItr.hasNext()) + { + sb.append(CR); + } + } + return sb.toString(); + } + + protected String generateProxyInnerClassGetMethodImpls(AmqpModel model, boolean serverFlag, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + String outerClassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + Iterator cItr = model.getClassMap().keySet().iterator(); + while (cItr.hasNext()) + { + AmqpClass thisClass = model.getClassMap().get(cItr.next()); + String className = thisClass.getName(); + String instanceName = parseForReservedWords(Utils.firstLower(thisClass.getName()), outerClassName); + sb.append(indent + outerClassName + "::" + className + "& " + + outerClassName + "::get" + className + "()" + CR); + sb.append(indent + "{" + CR); + if (thisClass.getVersionSet().size() != getVersionSet().size()) + { + sb.append(indent + tab + "if (!" + generateVersionCheck(thisClass.getVersionSet()) + ")" + CR); + sb.append(indent + tab + tab + "throw new ProtocolVersionException();" + CR); + } + sb.append(indent + tab + "return " + instanceName + ";" + CR); + sb.append(indent + "}" + CR); + if (cItr.hasNext()) + { + sb.append(CR); + } + } + return sb.toString(); + } + + protected String generateProxyInnerClassImpl(AmqpModel model, boolean serverFlag, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + boolean firstClassFlag = true; + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + String className = thisClass.getName(); + if (!firstClassFlag) + { + sb.append(CR); + } + sb.append(indent + "// ==================== class " + className + + " ====================" + CR); + sb.append(generateInnerClassMethodImpls(thisClass, serverFlag, indentSize, tabSize)); + firstClassFlag = false; + } + return sb.toString(); + } + + protected String generateInnerClassMethodImpls(AmqpClass thisClass, boolean serverFlag, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String outerclassName = "AMQP_" + (serverFlag ? "Server" : "Client") + "Proxy"; + boolean first = true; + for (String thisMethodName : thisClass.getMethodMap().keySet()) + { + AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); + String methodBodyClassName = thisClass.getName() + Utils.firstUpper(method.getName()) + "Body"; + boolean clientChassisFlag = method.getClientMethodFlagMap().isSet(); + boolean serverChassisFlag = method.getServerMethodFlagMap().isSet(); + boolean versionConsistentFlag = method.isVersionConsistent(getVersionSet()); + if ((serverFlag && serverChassisFlag) || (!serverFlag && clientChassisFlag)) + { + String methodName = parseForReservedWords(method.getName(), outerclassName + "." + thisClass.getName()); + AmqpOverloadedParameterMap overloadededParameterMap = + method.getOverloadedParameterLists(thisClass.getVersionSet(), this); + for (AmqpOrdinalFieldMap thisFieldMap : overloadededParameterMap.keySet()) + { + AmqpVersionSet versionSet = overloadededParameterMap.get(thisFieldMap); + if (!first) + { + sb.append(CR); + } + sb.append(indent + "void " + outerclassName + "::" + thisClass.getName() + "::" + + methodName + "( u_int16_t channel"); + sb.append(generateMethodParameterList(thisFieldMap, indentSize + (5 * tabSize), true, true, true)); + sb.append(" )"); + if (versionSet.size() != getVersionSet().size()) + { + sb.append(" // AMQP Version(s) " + versionSet); + } + sb.append(CR); + sb.append(indent + "{" + CR); + sb.append(generateMethodBodyCallContext(thisFieldMap, outerclassName, methodBodyClassName, + versionConsistentFlag, versionSet, indentSize + tabSize, tabSize)); + sb.append(indent + "}" + CR); + sb.append(CR); + first = false; + } + } + } + return sb.toString(); + } + + protected String generateMethodBodyCallContext(AmqpOrdinalFieldMap fieldMap, String outerclassName, + String methodBodyClassName, boolean versionConsistentFlag, AmqpVersionSet versionSet, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + if (versionConsistentFlag) + { + sb.append(generateMethodBodyCall(fieldMap, methodBodyClassName, null, indentSize, tabSize)); + } + else + { + boolean firstOverloadedMethodFlag = true; + for (AmqpVersion thisVersion : versionSet) + { + sb.append(indent); + if (!firstOverloadedMethodFlag) + { + sb.append("else "); + } + sb.append("if (" + generateVersionCheck(thisVersion) + ")" + CR); + sb.append(indent + "{" + CR); + sb.append(generateMethodBodyCall(fieldMap, methodBodyClassName, thisVersion, + indentSize + tabSize, tabSize)); + sb.append(indent + "}" + CR); + firstOverloadedMethodFlag = false; + } + sb.append(indent + "else" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab + "std::stringstream ss;" + CR); + sb.append(indent + tab + "ss << \"Call to " + outerclassName + "::" + methodBodyClassName + + "(u_int16_t" + generateMethodParameterList(fieldMap, 0, true, true, false) + ")\"" + CR); + sb.append(indent + tab + tab + "<< \" is invalid for AMQP version \" << version.toString() << \".\";" + CR); + sb.append(indent + tab + "throw new ProtocolVersionException(ss.str());" + CR); + sb.append(indent + "}" + CR); + } + return sb.toString(); + } + + protected String generateMethodBodyCall(AmqpOrdinalFieldMap fieldMap, String methodBodyClassName, + AmqpVersion version, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + String namespace = version != null ? version.namespace() + "::" : ""; + StringBuffer sb = new StringBuffer(indent + "out->send( new AMQFrame(parent->getProtocolVersion(), channel," + CR); + sb.append(indent + tab + "new " + namespace + methodBodyClassName + "( parent->getProtocolVersion()"); + sb.append(generateMethodParameterList(fieldMap, indentSize + (5 * tabSize), true, false, true)); + sb.append(" )));" + CR); + return sb.toString(); + } + + protected String generateMethodBodyIncludes(AmqpClass thisClass, int indentSize) + { + StringBuffer sb = new StringBuffer(); + if (thisClass != null) + { + sb.append(generateClassMethodBodyInclude(thisClass, indentSize)); + } + else + { + for (String thisClassName : getModel().getClassMap().keySet()) + { + thisClass = getModel().getClassMap().get(thisClassName); + sb.append(generateClassMethodBodyInclude(thisClass, indentSize)); + } + } + return sb.toString(); + } + + protected String generateClassMethodBodyInclude(AmqpClass thisClass, int indentSize) + { + StringBuffer sb = new StringBuffer(); + String indent = Utils.createSpaces(indentSize); + for (String thisMethodName : thisClass.getMethodMap().keySet()) + { + AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); + sb.append(indent + "#include <" + thisClass.getName() + + Utils.firstUpper(method.getName()) + "Body.h>" + CR); + } + return sb.toString(); + } + + // Methods used for generation of code snippets for MethodBody class generation + + protected String getIndex(AmqpOrdinalVersionMap indexMap, AmqpVersion version) + { + for (Integer thisIndex : indexMap.keySet()) + { + AmqpVersionSet versionSet = indexMap.get(thisIndex); + if (versionSet.contains(version)) + { + return String.valueOf(thisIndex); + } + } + throw new AmqpTemplateException("Unable to find index for version " + version); + } + + protected String generateFieldDeclarations(AmqpFieldMap fieldMap, AmqpVersion version, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + if (version == null) + { + version = getVersionSet().first(); + } + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); + for (Integer thisOrdinal : ordinalFieldMap.keySet()) + { + String[] fieldDomainPair = ordinalFieldMap.get(thisOrdinal); + sb.append(indent + fieldDomainPair[FIELD_CODE_TYPE] + " " + fieldDomainPair[FIELD_NAME] + ";" + CR); + } + return sb.toString(); + } + + protected String generateFieldGetMethods(AmqpFieldMap fieldMap, AmqpVersion version, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + if (version == null) + { + version = getVersionSet().first(); + } + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); + for (Integer thisOrdinal : ordinalFieldMap.keySet()) + { + String[] fieldDomainPair = ordinalFieldMap.get(thisOrdinal); + sb.append(indent + "inline " + setRef(fieldDomainPair[FIELD_CODE_TYPE]) + " get" + + Utils.firstUpper(fieldDomainPair[FIELD_NAME]) + "() { return " + + fieldDomainPair[FIELD_NAME] + "; }" + CR); + } + return sb.toString(); + } + + protected String generatePrintMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + if (version == null) + { + version = getVersionSet().first(); + } + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); + boolean firstFlag = true; + for (Integer thisOrdinal : ordinalFieldMap.keySet()) + { + String[] fieldDomainPair = ordinalFieldMap.get(thisOrdinal); + String cast = fieldDomainPair[FIELD_CODE_TYPE].compareTo("u_int8_t") == 0 ? "(int)" : ""; + sb.append(indent + "out << \""); + if (!firstFlag) + { + sb.append("; "); + } + sb.append(fieldDomainPair[FIELD_NAME] + "=\" << " + cast + fieldDomainPair[FIELD_NAME] + ";" + CR); + firstFlag = false; + } + return sb.toString(); + } + + protected String generateBodySizeMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + ArrayList bitFieldList = new ArrayList(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, false, this); + Iterator oItr = ordinalFieldMap.keySet().iterator(); + int ordinal = 0; + while (oItr.hasNext()) + { + ordinal = oItr.next(); + String[] fieldDomainPair = ordinalFieldMap.get(ordinal); + AmqpVersion thisVersion = version == null ? getVersionSet().first() : version; + String domainType = getDomainType(fieldDomainPair[FIELD_CODE_TYPE], thisVersion); + + // Defer bit types by adding them to an array. When the first subsequent non-bit + // type is encountered, then handle the bits. This allows consecutive bits to be + // placed into the same byte(s) - 8 bits to the byte. + if (domainType.compareTo("bit") == 0) + { + bitFieldList.add(fieldDomainPair[FIELD_NAME]); + } + else + { + if (bitFieldList.size() > 0) // Handle accumulated bit types (if any) + { + sb.append(generateBitArrayBodySizeMethodContents(bitFieldList, ordinal, indentSize)); + } + sb.append(indent + "size += " + + typeMap.get(domainType).size.replaceAll("#", fieldDomainPair[FIELD_NAME]) + + "; /* " + fieldDomainPair[FIELD_NAME] + ": " + + domainType + " */" + CR); + } + } + if (bitFieldList.size() > 0) // Handle any remaining accumulated bit types + { + sb.append(generateBitArrayBodySizeMethodContents(bitFieldList, ordinal, indentSize)); + } + return sb.toString(); + } + + protected String generateBitArrayBodySizeMethodContents(ArrayList bitFieldList, + int ordinal, int indentSize) + { + int numBytes = ((bitFieldList.size() - 1) / 8) + 1; + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + String comment = bitFieldList.size() == 1 ? + bitFieldList.get(0) + ": bit" : + "Combinded bits: " + bitFieldList; + sb.append(indent + "size += " + + typeMap.get("bit").size.replaceAll("~", String.valueOf(numBytes)) + + "; /* " + comment + " */" + CR); + bitFieldList.clear(); + return sb.toString(); + } + + protected String generateEncodeMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + ArrayList bitFieldList = new ArrayList(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, false, this); + Iterator oItr = ordinalFieldMap.keySet().iterator(); + int ordinal = 0; + while (oItr.hasNext()) + { + ordinal = oItr.next(); + String[] fieldDomainPair = ordinalFieldMap.get(ordinal); + AmqpVersion thisVersion = version == null ? getVersionSet().first() : version; + String domainType = getDomainType(fieldDomainPair[FIELD_CODE_TYPE], thisVersion); + + // Defer bit types by adding them to an array. When the first subsequent non-bit + // type is encountered, then handle the bits. This allows consecutive bits to be + // placed into the same byte(s) - 8 bits to the byte. + if (domainType.compareTo("bit") == 0) + { + bitFieldList.add(fieldDomainPair[FIELD_NAME]); + } + else + { + if (bitFieldList.size() > 0) // Handle accumulated bit types (if any) + { + sb.append(generateBitEncodeMethodContents(bitFieldList, ordinal, indentSize)); + } + sb.append(indent + + typeMap.get(domainType).encodeExpression.replaceAll("#", fieldDomainPair[FIELD_NAME]) + + "; /* " + fieldDomainPair[FIELD_NAME] + ": " + domainType + " */" + CR); + } + } + if (bitFieldList.size() > 0) // Handle any remaining accumulated bit types + { + sb.append(generateBitEncodeMethodContents(bitFieldList, ordinal, indentSize)); + } + + return sb.toString(); + } + + protected String generateBitEncodeMethodContents(ArrayList bitFieldList, int ordinal, + int indentSize) + { + int numBytes = ((bitFieldList.size() - 1) / 8) + 1; + String indent = Utils.createSpaces(indentSize); + String bitArrayName = "flags_" + ordinal; + StringBuffer sb = new StringBuffer(indent + "u_int8_t " + bitArrayName + + "[" + numBytes + "] = {0};" + + (numBytes != 1 ? " /* All array elements will be initialized to 0 */" : "") + + CR); + for (int i = 0; i < bitFieldList.size(); i++) + { + int bitIndex = i % 8; + int byteIndex = i / 8; + sb.append(indent + bitArrayName + "[" + byteIndex + "] |= " + bitFieldList.get(i) + + " << " + bitIndex + "; /* " + bitFieldList.get(i) + ": bit */" + CR); + } + for (int i = 0; i < numBytes; i++) + { + sb.append(indent + "buffer.putOctet(" + bitArrayName + "[" + i + "]);" + CR); + } + bitFieldList.clear(); + return sb.toString(); + } + + protected String generateDecodeMethodContents(AmqpFieldMap fieldMap, AmqpVersion version, + int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + ArrayList bitFieldList = new ArrayList(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, false, this); + Iterator oItr = ordinalFieldMap.keySet().iterator(); + int ordinal = 0; + while (oItr.hasNext()) + { + ordinal = oItr.next(); + String[] fieldDomainPair = ordinalFieldMap.get(ordinal); + AmqpVersion thisVersion = version == null ? getVersionSet().first() : version; + String domainType = getDomainType(fieldDomainPair[FIELD_CODE_TYPE], thisVersion); + + // Defer bit types by adding them to an array. When the first subsequent non-bit + // type is encountered, then handle the bits. This allows consecutive bits to be + // placed into the same byte(s) - 8 bits to the byte. + if (domainType.compareTo("bit") == 0) + { + bitFieldList.add(fieldDomainPair[FIELD_NAME]); + } + else + { + if (bitFieldList.size() > 0) // Handle accumulated bit types (if any) + { + sb.append(generateBitDecodeMethodContents(bitFieldList, ordinal, indentSize)); + } + sb.append(indent + + typeMap.get(domainType).decodeExpression.replaceAll("#", fieldDomainPair[FIELD_NAME]) + + "; /* " + fieldDomainPair[FIELD_NAME] + ": " + domainType + " */" + CR); + } + } + if (bitFieldList.size() > 0) // Handle any remaining accumulated bit types + { + sb.append(generateBitDecodeMethodContents(bitFieldList, ordinal, indentSize)); + } + + return sb.toString(); + } + + protected String generateBitDecodeMethodContents(ArrayList bitFieldList, int ordinal, + int indentSize) + { + int numBytes = ((bitFieldList.size() - 1) / 8) + 1; + String indent = Utils.createSpaces(indentSize); + String bitArrayName = "flags_" + ordinal; + StringBuffer sb = new StringBuffer(indent + "u_int8_t " + bitArrayName + + "[" + numBytes + "];" + CR); + for (int i = 0; i < numBytes; i++) + { + sb.append(indent + bitArrayName + "[" + i + "] = buffer.getOctet();" + CR); + } + for (int i = 0; i < bitFieldList.size(); i++) + { + int bitIndex = i % 8; + int byteIndex = i / 8; + sb.append(indent + bitFieldList.get(i) + " = (1 << " + bitIndex + ") & " + + bitArrayName + "[" + byteIndex + "]; /* " + bitFieldList.get(i) + + ": bit */" + CR); + } + bitFieldList.clear(); + return sb.toString(); + } + + protected String generateFieldList(AmqpFieldMap fieldMap, AmqpVersion version, boolean defineFlag, + boolean initializerFlag, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + AmqpOrdinalFieldMap ordinalFieldMap = fieldMap.getMapForVersion(version, true, this); + Iterator oItr = ordinalFieldMap.keySet().iterator(); + while (oItr.hasNext()) + { + int ordinal = oItr.next(); + String[] fieldDomainPair = ordinalFieldMap.get(ordinal); + sb.append(indent + (defineFlag ? setRef(fieldDomainPair[FIELD_CODE_TYPE]) + " " : "") + + fieldDomainPair[FIELD_NAME] + (initializerFlag ? "(" + fieldDomainPair[FIELD_NAME] + ")" : "") + + (oItr.hasNext() ? "," : "") + CR); + } + return sb.toString(); + } + + protected String generateMethodParameterList(AmqpOrdinalFieldMap fieldMap, int indentSize, + boolean leadingCommaFlag, boolean fieldTypeFlag, boolean fieldNameFlag) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + boolean first = true; + Iterator pItr = fieldMap.keySet().iterator(); + while (pItr.hasNext()) + { + String[] field = fieldMap.get(pItr.next()); + if (first && leadingCommaFlag) + { + sb.append("," + (fieldNameFlag ? CR : " ")); + } + if (!first || leadingCommaFlag) + { + sb.append(indent); + } + sb.append( + (fieldTypeFlag ? setRef(field[FIELD_CODE_TYPE]) : "") + + (fieldNameFlag ? " " + field[FIELD_NAME] : "") + + (pItr.hasNext() ? "," + (fieldNameFlag ? CR : " ") : "")); + first = false; + } + return sb.toString(); + } + + protected String generateConstructor(AmqpClass thisClass, AmqpMethod method, + AmqpVersion version, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + if (method.getFieldMap().size() > 0) + { + sb.append(indent + thisClass.getName() + Utils.firstUpper(method.getName()) + "Body(ProtocolVersion& version," + CR); + sb.append(generateFieldList(method.getFieldMap(), version, true, false, 8)); + sb.append(indent + tab + ") :" + CR); + sb.append(indent + tab + "AMQMethodBody(version)," + CR); + sb.append(generateFieldList(method.getFieldMap(), version, false, true, 8)); + sb.append(indent + "{ }" + CR); + } + return sb.toString(); + } + + protected String generateServerOperationsInvoke(AmqpClass thisClass, AmqpMethod method, + AmqpVersion version, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + + if (method.getServerMethodFlagMap().size() > 0) // At least one AMQP version defines this method as a server method + { + Iterator bItr = method.getServerMethodFlagMap().keySet().iterator(); + while (bItr.hasNext()) + { + if (bItr.next()) // This is a server operation + { + boolean fieldMapNotEmptyFlag = method.getFieldMap().size() > 0; + sb.append(indent + "inline void invoke(AMQP_ServerOperations& target, u_int16_t channel)" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab + "target.get" + thisClass.getName() + "Handler()->" + + parseForReservedWords(Utils.firstLower(method.getName()), + thisClass.getName() + Utils.firstUpper(method.getName()) + "Body.invoke()") + "(channel"); + if (fieldMapNotEmptyFlag) + { + sb.append("," + CR); + sb.append(generateFieldList(method.getFieldMap(), version, false, false, indentSize + 4 * tabSize)); + sb.append(indent + tab + tab + tab + tab); + } + sb.append(");" + CR); + sb.append(indent + "}" + CR); + } + } + } + return sb.toString(); + } + + // Methods for generation of code snippets for amqp_methods.h/cpp files + + protected String generateMethodBodyIncludeList(AmqpModel model, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + for (String thisMethodName : thisClass.getMethodMap().keySet()) + { + AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); + sb.append(indent + "#include \"" + thisClass.getName() + Utils.firstUpper(method.getName()) + "Body.h\"" + CR); + } + } + + return sb.toString(); + } + + protected String generateMethodBodyInstances(AmqpModel model, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + for (String thisMethodName : thisClass.getMethodMap().keySet()) + { + AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); + sb.append(indent + "const " + thisClass.getName() + Utils.firstUpper(method.getName()) + "Body " + + Utils.firstLower(thisClass.getName()) + "_" + method.getName() + ";" + CR); + } + } + + return sb.toString(); + } + + protected String generateMethodBodyMapEntry(AmqpModel model, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + for (AmqpVersion version : getVersionSet()) + { + for (String thisClassName : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(thisClassName); + for (String thisMethodName : thisClass.getMethodMap().keySet()) + { + AmqpMethod method = thisClass.getMethodMap().get(thisMethodName); + String namespace = method.isVersionConsistent(getVersionSet()) ? "" : version.namespace() + "::"; + try + { + int classOrdinal = thisClass.getIndexMap().getOrdinal(version); + int methodOrdinal = method.getIndexMap().getOrdinal(version); + String methodModyClassName = namespace + thisClass.getName() + Utils.firstUpper(method.getName()) + "Body"; + sb.append(indent + "insert(std::make_pair(createMapKey(" + classOrdinal + ", " + + methodOrdinal + ", " + version.getMajor() + ", " + version.getMinor() + + "), &createMethodBodyFn<" + methodModyClassName + ">));" + CR); + } + catch (AmqpTypeMappingException e) + { + } // ignore + } + } + } + + return sb.toString(); + } + + // Helper functions + + private String generateVersionCheck(AmqpVersion version) + { + return "version.equals(" + version.getMajor() + ", " + version.getMinor() + ")"; + } + + private String generateVersionCheck(AmqpVersionSet versionSet) + { + StringBuffer sb = new StringBuffer(); + for (AmqpVersion v : versionSet) + { + if (!v.equals(versionSet.first())) + { + sb.append(" || "); + } + if (versionSet.size() > 1) + { + sb.append("("); + } + sb.append("version.equals(" + v.getMajor() + ", " + v.getMinor() + ")"); + if (versionSet.size() > 1) + { + sb.append(")"); + } + } + return sb.toString(); + } + + private String parseForReservedWords(String name, String context) + { + for (String cppReservedWord : cppReservedWords) + { + if (name.compareTo(cppReservedWord) == 0) + { + if (!quietFlag) + { + System.out.println("WARNING: " + (context == null ? "" : context + ": ") + + "Found XML method \"" + name + "\", which is a C++ reserved word. " + + "Changing generated name to \"" + name + "_\"."); + } + return name + "_"; + } + } + + for (String cppCommonDefine : cppCommonDefines) + { + if (name.compareTo(cppCommonDefine) == 0) + { + if (!quietFlag) + { + System.out.println("WARNING: " + (context == null ? "" : context + ": ") + + "Found XML method \"" + name + "\", which may clash with commonly used defines within C++. " + + "Changing generated name to \"" + name + "_\"."); + } + return name + "_"; + } + } + + return name; + } + + private String setRef(String codeType) + { + if (codeType.compareTo("string") == 0 || + codeType.compareTo("FieldTable") == 0) + { + return "const " + codeType + "&"; + } + return codeType; + } + + private String camelCaseName(String name, boolean upperFirstFlag) + { + StringBuffer ccn = new StringBuffer(); + String[] toks = name.split("[-_.\\ ]"); + for (int i = 0; i < toks.length; i++) + { + StringBuffer b = new StringBuffer(toks[i]); + if (upperFirstFlag || i > 0) + { + b.setCharAt(0, Character.toUpperCase(toks[i].charAt(0))); + } + ccn.append(b); + } + return ccn.toString(); + } + + public static Factory _factoryInstance = new Factory() + { + + public CppGenerator newInstance() + { + return new CppGenerator(); + } + }; + + public static Factory getFactory() + { + return _factoryInstance; + } + + void processModelTemplate(NamedTemplate template, AmqpVersion version) + { + //To change body of implemented methods use File | Settings | File Templates. + } + public String getNativeType(String type) + { + throw new UnsupportedOperationException(); + } + + public String getEncodingType(String type) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java b/java/common/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java new file mode 100644 index 0000000000..9fc81dd428 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/DotnetGenerator.java @@ -0,0 +1,382 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.gentools; + +import java.io.File; +import java.util.TreeMap; + +public class DotnetGenerator extends Generator +{ + private class DomainInfo + { + public String type; + public String size; + public String encodeExpression; + public String decodeExpression; + + public DomainInfo(String domain, String size, String encodeExpression, String decodeExpression) + { + this.type = domain; + this.size = size; + this.encodeExpression = encodeExpression; + this.decodeExpression = decodeExpression; + } + } + + private static TreeMap typeMap = new TreeMap(); + + public String getNativeType(String type) + { + throw new UnsupportedOperationException(); + } + + public String getEncodingType(String type) + { + throw new UnsupportedOperationException(); + } + + public DotnetGenerator() + { + super(); + // Load .NET type and size maps. + // Adjust or add to these lists as new types are added/defined. + // The char '#' will be replaced by the field variable name (any type). + // The char '~' will be replaced by the compacted bit array size (type bit only). + // TODO: I have left a copy of the Java typeMap here - replace with appropriate .NET values. + typeMap.put("bit", new DomainInfo( + "boolean", // .NET code type + "~", // size + "EncodingUtils.writeBooleans(buffer, #)", // encode expression + "# = EncodingUtils.readBooleans(buffer)")); // decode expression + typeMap.put("content", new DomainInfo( + "Content", // .NET code type + "EncodingUtils.encodedContentLength(#)", // size + "EncodingUtils.writeContentBytes(buffer, #)", // encode expression + "# = EncodingUtils.readContent(buffer)")); // decode expression + typeMap.put("long", new DomainInfo( + "long", // .NET code type + "4", // size + "EncodingUtils.writeUnsignedInteger(buffer, #)", // encode expression + "# = buffer.getUnsignedInt()")); // decode expression + typeMap.put("longlong", new DomainInfo( + "long", // .NET code type + "8", // size + "buffer.putLong(#)", // encode expression + "# = buffer.getLong()")); // decode expression + typeMap.put("longstr", new DomainInfo( + "byte[]", // .NET code type + "EncodingUtils.encodedLongstrLength(#)", // size + "EncodingUtils.writeLongStringBytes(buffer, #)", // encode expression + "# = EncodingUtils.readLongstr(buffer)")); // decode expression + typeMap.put("octet", new DomainInfo( + "short", // .NET code type + "1", // size + "EncodingUtils.writeUnsignedByte(buffer, #)", // encode expression + "# = buffer.getUnsigned()")); // decode expression + typeMap.put("short", new DomainInfo( + "int", // .NET code type + "2", // size + "EncodingUtils.writeUnsignedShort(buffer, #)", // encode expression + "# = buffer.getUnsignedShort()")); // decode expression + typeMap.put("shortstr", new DomainInfo( + "AMQShortString", // .NET code type + "EncodingUtils.encodedShortStringLength(#)", // size + "EncodingUtils.writeShortStringBytes(buffer, #)", // encode expression + "# = EncodingUtils.readAMQShortString(buffer)")); // decode expression + typeMap.put("table", new DomainInfo( + "FieldTable", // .NET code type + "EncodingUtils.encodedFieldTableLength(#)", // size + "EncodingUtils.writeFieldTableBytes(buffer, #)", // encode expression + "# = EncodingUtils.readFieldTable(buffer)")); // decode expression + typeMap.put("timestamp", new DomainInfo( + "long", // .NET code type + "8", // size + "EncodingUtils.writeTimestamp(buffer, #)", // encode expression + "# = EncodingUtils.readTimestamp(buffer)")); // decode expression + } + + void processModelTemplate(NamedTemplate template, AmqpVersion version) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + void processClassTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpVersion version) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + void processMethodTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpVersion version) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + void processFieldTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpField amqpField, AmqpVersion version) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + protected String prepareFilename(String filenameTemplate, + AmqpClass thisClass, AmqpMethod method, AmqpField field, AmqpVersion version) + { + StringBuffer sb = new StringBuffer(filenameTemplate); + if (thisClass != null) + { + replaceToken(sb, "${CLASS}", thisClass.getName()); + } + if (method != null) + { + replaceToken(sb, "${METHOD}", method.getName()); + } + if (field != null) + { + replaceToken(sb, "${FIELD}", field.getName()); + } + return sb.toString(); + } + + @Override + protected void processClassList(StringBuffer sb, int listMarkerStartIndex, + int listMarkerEndIndex, AmqpModel model, AmqpVersion version) + throws AmqpTemplateException, AmqpTypeMappingException + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + // TODO: Add in tokens and calls to their corresponding generator methods here... + if (token.compareTo("${??????????}") == 0) + { + codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present. +// codeSnippet = generateRegistry(model, 8, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processConstantList(StringBuffer sb, + int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet) throws AmqpTemplateException, + AmqpTypeMappingException + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + // TODO: Add in tokens and calls to their corresponding generator methods here... + if (token.compareTo("${??????????}") == 0) + { + codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present. +// codeSnippet = generateConstantGetMethods(constantSet, 4, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, + int listMarkerEndIndex, AmqpFieldMap fieldMap, AmqpVersion version) + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + // TODO: Add in tokens and calls to their corresponding generator methods here... + if (token.compareTo("${??????????}") == 0) + { + codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present. +// codeSnippet = fieldMap.parseFieldMap(declarationGenerateMethod, +// mangledDeclarationGenerateMethod, 4, 4, this); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, + int listMarkerEndIndex, AmqpClass thisClass) + throws AmqpTemplateException, AmqpTypeMappingException + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + // TODO: Add in tokens and calls to their corresponding generator methods here... + if (token.compareTo("${??????????}") == 0) + { + codeSnippet = token; // This is a stub to get the compile working - remove when gen method is present. + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processModelTemplate(NamedTemplate template) + { + // I've put in the Java model here - this can be changed if a different pattern is required. + processTemplate(template, null, null, null, null); + } + + @Override + protected void processClassTemplate(NamedTemplate template, AmqpClass thisClass) + { + // I've put in the Java model here - this can be changed if a different pattern is required. + processTemplate(template, thisClass, null, null, null); + } + + @Override + protected void processMethodTemplate(NamedTemplate template, AmqpClass thisClass, + AmqpMethod method) + { + // I've put in the Java model here - this can be changed if a different pattern is required. + processTemplate(template, thisClass, method, null, null); + } + + @Override + protected void processTemplate(NamedTemplate template, AmqpClass thisClass, + AmqpMethod method, AmqpField field, AmqpVersion version) + { + // I've put in the Java model here - this can be changed if a different pattern is required. + StringBuffer sb = new StringBuffer(template.getTemplate()); + String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, field, version); + try + { + processAllLists(sb, thisClass, method, null); + } + catch (AmqpTemplateException e) + { + System.out.println("WARNING: " + template.getName() + ": " + e.getMessage()); + } + try + { + processAllTokens(sb, thisClass, method, field, null); + } + catch (AmqpTemplateException e) + { + System.out.println("WARNING: " + template.getName() + ": " + e.getMessage()); + } + writeTargetFile(sb, new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename)); + generatedFileCounter++; + } + + @Override + protected String processToken(String token, AmqpClass thisClass, + AmqpMethod method, AmqpField field, AmqpVersion version) + throws AmqpTemplateException, AmqpTypeMappingException + { + // TODO Auto-generated method stub + return null; + } + + public String getGeneratedType(String domainName, AmqpVersion version) + throws AmqpTypeMappingException + { + String domainType = getDomainType(domainName, version); + if (domainType == null) + { + throw new AmqpTypeMappingException("Domain type \"" + domainName + + "\" not found in Java typemap."); + } + DomainInfo info = typeMap.get(domainType); + if (info == null) + { + throw new AmqpTypeMappingException("Unknown domain: \"" + domainType + "\""); + } + return info.type; + } + + public String prepareClassName(String className) + { + return camelCaseName(className, true); + } + + public String prepareDomainName(String domainName) + { + return camelCaseName(domainName, false); + } + + public String prepareMethodName(String methodName) + { + return camelCaseName(methodName, false); + } + + private String camelCaseName(String name, boolean upperFirstFlag) + { + StringBuffer ccn = new StringBuffer(); + String[] toks = name.split("[-_.\\ ]"); + for (int i = 0; i < toks.length; i++) + { + StringBuffer b = new StringBuffer(toks[i]); + if (upperFirstFlag || i > 0) + { + b.setCharAt(0, Character.toUpperCase(toks[i].charAt(0))); + } + ccn.append(b); + } + return ccn.toString(); + } + + + public static Factory _factoryInstance = new Factory() + { + + public DotnetGenerator newInstance() + { + return new DotnetGenerator(); + } + }; + + public static Factory getFactory() + { + return _factoryInstance; + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/GenerateMethod.java b/java/common/gentools/src/org/apache/qpid/gentools/GenerateMethod.java new file mode 100644 index 0000000000..8b0bb99b41 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/GenerateMethod.java @@ -0,0 +1,27 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + + +public interface GenerateMethod +{ + String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize); +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/Generator.java b/java/common/gentools/src/org/apache/qpid/gentools/Generator.java new file mode 100644 index 0000000000..5d6e7be527 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/Generator.java @@ -0,0 +1,857 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.w3c.dom.Node; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +public abstract class Generator implements LanguageConverter +{ + protected static String CR = Utils.LINE_SEPARATOR; + + + private static final Map FIXED_SIZE_TYPES = new HashMap(); + + static + { + FIXED_SIZE_TYPES.put("bit", 1); + FIXED_SIZE_TYPES.put("bitfield", 1); + FIXED_SIZE_TYPES.put("long", 4); + FIXED_SIZE_TYPES.put("longlong", 8); + FIXED_SIZE_TYPES.put("octet", 1); + FIXED_SIZE_TYPES.put("short", 2); + FIXED_SIZE_TYPES.put("timestamp", 8); + + } + + private String _templateDirectory; + private String _outputDirectory; + + public AmqpDomainMap getDomainMap() + { + return _domainMap; + } + + public AmqpConstantSet getConstantSet() + { + return _constantSet; + } + + public AmqpModel getModel() + { + return _model; + } + + abstract public String getNativeType(String type); + + abstract public String getEncodingType(String type); + + + + protected static enum EnumConstOutputTypes + { + OUTPUT_STRING, + OUTPUT_INTEGER, + OUTPUT_DOUBLE; + } + + ; + + public static enum TemplateType + { + model("model"), + clazz("class"), + method("method"), + field("field"); + + private final String _name; + + private TemplateType(String name) + { + _name = name; + } + + public String getName() + { + return _name; + } + } + + ; + + + public static interface Factory + { + public X newInstance(); + } + + + protected static final class NamedTemplate + { + private final String _name; + private final String _template; + private final File _file; + + + public NamedTemplate(String relativePath, File templateFile) + { + _file = templateFile; + _name = relativePath + Utils.FILE_SEPARATOR + templateFile.getName(); + + _template = loadTemplate(templateFile); + } + + + public String getName() + { + return _name; + } + + public String getTemplate() + { + return _template; + } + + + public File getFile() + { + return _file; + } + + } + + + private static final String VELOCITY_TEMPLATE_SUFFIX = ".vm"; + private static final String STANDARD_TEMPLATE_SUFFIX = ".tmpl"; + private static FilenameFilter _tmplFileFilter = new FilenameFilter() + { + + public boolean accept(File dir, String name) + { + return name.endsWith(STANDARD_TEMPLATE_SUFFIX) || name.endsWith(VELOCITY_TEMPLATE_SUFFIX); + } + }; + + + // This string is reproduced in every generated file as a comment + // TODO: Tie the version info into the build system. + protected static final String GENERATOR_INFO = "Qpid Gentools v.0.1"; + + + private final Map> _templates = + new EnumMap>(TemplateType.class); + + private final Map> _versionSpecificTemplates = + new EnumMap>(TemplateType.class); + + + private final AmqpVersionSet _versionSet; + + private final AmqpDomainMap _domainMap; + private final Map _versionToDomainMapMap = new HashMap(); + + private final AmqpConstantSet _constantSet; + private final Map _versionToConstantSetMap = new HashMap(); + + + public AmqpVersionSet getVersionSet() + { + return _versionSet; + } + + private final AmqpModel _model; + private final Map _versionToModelMap = new HashMap(); + + protected int generatedFileCounter; + + public Generator() + { + _versionSet = new AmqpVersionSet(); + _model = new AmqpModel(this); + _constantSet = new AmqpConstantSet(this); + _domainMap = new AmqpDomainMap(this); + + generatedFileCounter = 0; + } + +// public final AmqpVersionSet getVersionSet() +// { +// return _versionSet; +// } + + + public void addVersion(AmqpVersion version) + { + _versionSet.add(version); + if (!_versionToModelMap.containsKey(version)) + { + _versionToModelMap.put(version, new AmqpModel(this)); + } + if (!_versionToDomainMapMap.containsKey(version)) + { + _versionToDomainMapMap.put(version, new AmqpDomainMap(this)); + } + if (!_versionToConstantSetMap.containsKey(version)) + { + _versionToConstantSetMap.put(version, new AmqpConstantSet(this)); + } + } + + public int getNumberGeneratedFiles() + { + return generatedFileCounter; + } + +// public AmqpDomainMap getDomainMap() +// { +// return _domainMap; +// } +// +// public AmqpConstantSet getConstantSet() +// { +// return _constantSet; +// } +// +// +// public AmqpModel getModel() +// { +// return _model; +// } + + public void initializeTemplates() throws IOException + { + + for (TemplateType type : EnumSet.allOf(TemplateType.class)) + { + ArrayList typeTemplates = new ArrayList(); + _templates.put(type, typeTemplates); + ArrayList versionSpecificTypeTemplates = new ArrayList(); + _versionSpecificTemplates.put(type, versionSpecificTypeTemplates); + + File templateDirectory = new File(getTemplateDirectory() + Utils.FILE_SEPARATOR + type.getName()); + File versionTemplateDirectory = new File(getTemplateDirectory() + Utils.FILE_SEPARATOR + type.getName() + Utils.FILE_SEPARATOR + "version"); + + System.out.println("Looking for template files in directory: " + templateDirectory.getAbsoluteFile()); + + File[] templateFiles = templateDirectory.listFiles(_tmplFileFilter); + + File[] versionTemplateFiles = new File[0]; + + System.out.println("Looking for version specific template files in directory: " + versionTemplateDirectory.getAbsoluteFile()); + + if (versionTemplateDirectory.exists()) + { + versionTemplateFiles = versionTemplateDirectory.listFiles(_tmplFileFilter); + } + + if(templateFiles != null) + { + for (File templateFile : templateFiles) + { + System.out.println(type.getName() + " template file(s):"); + System.out.println(" " + templateFile.getCanonicalPath()); + typeTemplates.add(new NamedTemplate(type.getName(), templateFile)); + } + } + + if(versionTemplateFiles != null) + { + for (File versionTemplateFile : versionTemplateFiles) + { + System.out.println(type.getName() + " template file(s):"); + System.out.println(" " + versionTemplateFile.getCanonicalPath()); + versionSpecificTypeTemplates.add(new NamedTemplate(type.getName() + Utils.FILE_SEPARATOR + "version", versionTemplateFile)); + } + } + + } + } + + public String getTemplateDirectory() + { + return _templateDirectory; + } + + + public void setTemplateDirectory(String templateDirectory) + { + _templateDirectory = templateDirectory; + } + + + public void setOutputDirectory(String outputDirectory) + { + _outputDirectory = outputDirectory; + } + + public void generate() + { + prepareTargetDirectory(new File(_outputDirectory), true); + System.out.println("Generation directory: " + _outputDirectory); + + + processModelTemplates(_templates); + + for (AmqpClass amqpClass : _model.getClassMap().values()) + { + processClassTemplates(_templates, amqpClass); + + for (AmqpMethod amqpMethod : amqpClass.getMethodMap().values()) + { + processMethodTemplates(_templates, amqpClass, amqpMethod); + + for (AmqpField amqpField : amqpMethod.getFieldMap().values()) + { + processFieldTemplates(_templates, amqpClass, amqpMethod, amqpField, null); + } + } + } + + + for (AmqpVersion version : _versionSet) + { + AmqpModel model = _versionToModelMap.get(version); + processModelTemplates(_versionSpecificTemplates, version); + + for (AmqpClass amqpClass : model.getClassMap().values()) + { + processClassTemplates(_versionSpecificTemplates, amqpClass, version); + + for (AmqpMethod amqpMethod : amqpClass.getMethodMap().values()) + { + processMethodTemplates(_versionSpecificTemplates, amqpClass, amqpMethod, version); + + for (AmqpField amqpField : amqpMethod.getFieldMap().values()) + { + processFieldTemplates(_versionSpecificTemplates, amqpClass, amqpMethod, amqpField, version); + } + } + } + + } + } + + private void processMethodTemplates(Map> templates, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpVersion version) + { + for (NamedTemplate template : templates.get(TemplateType.method)) + { + if(isVelocityTemplate(template)) + { + processVelocityTemplate(template,version,amqpClass,amqpMethod,null); + } + else + { + processMethodTemplate(template, amqpClass, amqpMethod); + } + } + + } + + private void processClassTemplates(Map> templates, AmqpClass amqpClass, AmqpVersion version) + { + for (NamedTemplate template : templates.get(TemplateType.clazz)) + { + if(isVelocityTemplate(template)) + { + processVelocityTemplate(template,version,amqpClass,null,null); + } + else + { + processClassTemplate(template, amqpClass); + } + } + + } + + + private void processModelTemplates(Map> templates, AmqpVersion version) + { + for (NamedTemplate template : templates.get(TemplateType.model)) + { + if (isVelocityTemplate(template)) + { + processModelVelocityTemplate(template, version); + } + else + { + processModelTemplate(template, version); + } + } + } + + abstract void processModelTemplate(NamedTemplate template, AmqpVersion version); + + + protected void processModelTemplates(Map> templates) + { + for (NamedTemplate template : templates.get(TemplateType.model)) + { + if (isVelocityTemplate(template)) + { + processModelVelocityTemplate(template, null); + } + else + { + processModelTemplate(template); + } + } + } + + private boolean isVelocityTemplate(NamedTemplate template) + { + return template.getName().endsWith(VELOCITY_TEMPLATE_SUFFIX); + } + + private void processModelVelocityTemplate(NamedTemplate template, AmqpVersion version) + { + processVelocityTemplate(template,version,null,null,null); + } + + private void processVelocityTemplate(NamedTemplate template, AmqpVersion version, + AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpField amqpField) + { + + VelocityContext context = new VelocityContext(); + + AmqpModel model = _model; + if(version != null) + { + model = _versionToModelMap.get(version); + } + context.put("model", model); + context.put("generator", GENERATOR_INFO); + + if (version != null) + { + context.put("version", version); + } + if(amqpClass != null) + { + context.put("amqpClass", amqpClass); + } + + if(amqpClass != null) + { + context.put("amqpMethod", amqpMethod); + } + + + StringWriter sw = new StringWriter(); + + + try + { + Template velocityTemplate = Velocity.getTemplate(template.getName()); + velocityTemplate.merge(context, sw); + String filename = String.valueOf(context.get("filename")); + + File outputFile = new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename); + outputFile.getParentFile().mkdirs(); + FileWriter outputFileWriter = new FileWriter(outputFile); + + outputFileWriter.append(sw.toString()); + outputFileWriter.close(); + + } + catch (Exception e) + { + e.printStackTrace(); + } + + + } + + + protected void processClassTemplates(Map> templates, AmqpClass amqpClass) + { + for (NamedTemplate template : templates.get(TemplateType.clazz)) + { + if(isVelocityTemplate(template)) + { + processVelocityTemplate(template,null,amqpClass,null,null); + } + else + { + processClassTemplate(template, amqpClass); + } + } + } + + protected void processMethodTemplates(Map> templates, AmqpClass amqpClass, AmqpMethod amqpMethod) + { + for (NamedTemplate template : templates.get(TemplateType.method)) + { + if(isVelocityTemplate(template)) + { + processVelocityTemplate(template,null,amqpClass,amqpMethod,null); + } + else + { + processMethodTemplate(template, amqpClass, amqpMethod); + } + } + } + + + protected void processFieldTemplates(Map> templates, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpField amqpField, AmqpVersion amqpVersion) + { + for (NamedTemplate template : templates.get(TemplateType.field)) + { + if(isVelocityTemplate(template)) + { + processVelocityTemplate(template,amqpVersion,amqpClass,amqpMethod,amqpField); + } + else + { + processTemplate(template, amqpClass, amqpMethod, amqpField, amqpVersion); + } + } + } + + + protected void processVersionList(StringBuffer sb, int tokStart, int tokEnd) + { + int lend = sb.indexOf(Utils.LINE_SEPARATOR, tokStart) + 1; // Include cr at end of line + String tline = sb.substring(tokEnd, lend); // Line excluding line marker, including cr + sb.delete(tokStart, lend); + + for (AmqpVersion v : _versionSet) + { + // Insert copy of target line + StringBuffer isb = new StringBuffer(tline); + if (isb.indexOf("${protocol-version-list-entry}") >= 0) + { + String versionListEntry = " { ${major}, ${minor} }" + + (v.equals(_versionSet.last()) ? "" : ","); + replaceToken(isb, "${protocol-version-list-entry}", String.valueOf(versionListEntry)); + } + if (isb.indexOf("${major}") >= 0) + { + replaceToken(isb, "${major}", String.valueOf(v.getMajor())); + } + if (isb.indexOf("${minor}") >= 0) + { + replaceToken(isb, "${minor}", String.valueOf(v.getMinor())); + } + sb.insert(tokStart, isb.toString()); + tokStart += isb.length(); + } + } + + // Helper functions common to all generators + + protected static void prepareTargetDirectory(File dir, boolean createFlag) + { + if (dir.exists()) + { + if (!dir.isDirectory()) + { + throw new TargetDirectoryException("\"" + dir.getAbsolutePath() + + "\" exists, but is not a directory."); + } + } + else if (createFlag) // Create dir + { + if (!dir.mkdirs()) + { + throw new TargetDirectoryException("Unable to create directory \"" + + dir.getAbsolutePath() + "\"."); + } + } + else + { + throw new TargetDirectoryException("Directory \"" + dir.getAbsolutePath() + + "\" not found."); + } + + } + + protected void processAllLists(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, AmqpVersion version) + { + AmqpModel model = (version == null) ? _model : _versionToModelMap.get(version); + + + int lstart = sb.indexOf("%{"); + while (lstart != -1) + { + int lend = sb.indexOf("}", lstart + 2); + if (lend > 0) + { + String listToken = sb.substring(lstart + 2, lend); + if (listToken.compareTo("VLIST") == 0) + { + processVersionList(sb, lstart, lend + 1); + } + else if (listToken.compareTo("CLIST") == 0) + { + processClassList(sb, lstart, lend + 1, model, version); + } + else if (listToken.compareTo("MLIST") == 0) + { + processMethodList(sb, lstart, lend + 1, thisClass); + } + else if (listToken.compareTo("FLIST") == 0) + { + // Pass the FieldMap from either a class or a method. + // If this is called from a class-level template, we assume that the + // class field list is required. In this case, method will be null. + processFieldList(sb, lstart, lend + 1, + (method == null ? thisClass.getFieldMap() : method.getFieldMap()), + version); + } + else if (listToken.compareTo("TLIST") == 0) + { + processConstantList(sb, lstart, lend + 1, _constantSet); + } + else + { + throw new AmqpTemplateException("Unknown list token \"%{" + listToken + + "}\" found in template at index " + lstart + "."); + } + } + lstart = sb.indexOf("%{", lstart + 1); + } + } + + protected void processAllTokens(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, AmqpField field, + AmqpVersion version) + { + int lstart = sb.indexOf("${"); + while (lstart != -1) + { + int lend = sb.indexOf("}", lstart + 2); + if (lend > 0) + { + String token = sb.substring(lstart, lend + 1); + replaceToken(sb, lstart, token, processToken(token, thisClass, method, field, version)); + } + lstart = sb.indexOf("${", lstart); + } + } + + protected static void writeTargetFile(StringBuffer sb, File f) + { + try + { + f.getParentFile().mkdirs(); + FileWriter fw = new FileWriter(f); + fw.write(sb.toString().toCharArray()); + fw.flush(); + fw.close(); + } + catch (IOException e) + { + throw new AmqpTemplateException(e.getMessage()); + } + } + + + protected static String getTemplateFileName(StringBuffer sb) + { + if (sb.charAt(0) != '&') + { + throw new AmqpTemplateException("No filename marker &{filename} found at start of template."); + } + int cr = sb.indexOf(Utils.LINE_SEPARATOR); + if (cr < 0) + { + throw new AmqpTemplateException("Bad template structure - unable to find first line."); + } + String fileName = sb.substring(2, cr - 1); + sb.delete(0, cr + 1); + return fileName; + } + + protected static void replaceToken(StringBuffer sb, String token, String replacement) + { + replaceToken(sb, 0, token, replacement); + } + + protected static void replaceToken(StringBuffer sb, int index, String token, String replacement) + { + if (replacement != null) + { + int start = sb.indexOf(token, index); + if (start != -1) + { + int len = token.length(); + // Find first letter in token and determine if it is capitalized + char firstTokenLetter = getFirstLetter(token); + if (firstTokenLetter != 0 && Character.isUpperCase(firstTokenLetter)) + { + sb.replace(start, start + len, Utils.firstUpper(replacement)); + } + else + { + sb.replace(start, start + len, replacement); + } + } + } + } + + private static char getFirstLetter(String str) + { + int len = str.length(); + int index = 0; + char tokChar = str.charAt(index); + while (!Character.isLetter(tokChar) && index < len - 1) + { + tokChar = str.charAt(++index); + } + if (Character.isLetter(tokChar)) + { + return tokChar; + } + return 0; + } + + private static String loadTemplate(File f) + { + try + { + StringBuffer sb = new StringBuffer(); + FileReader fr = new FileReader(f); + LineNumberReader lnr = new LineNumberReader(fr); + String line = lnr.readLine(); + while (line != null) + { + + sb.append(line); + sb.append(Utils.LINE_SEPARATOR); + + line = lnr.readLine(); + } + lnr.close(); + fr.close(); + return sb.toString(); + } + catch (FileNotFoundException e) + { + throw new AmqpTemplateException("File not found: " + e.getMessage()); + } + catch (IOException e) + { + throw new AmqpTemplateException("IOException: " + e.getMessage()); + } + } + + public String getDomainType(String domainName, AmqpVersion version) + { + if (version == null) + { + version = _versionSet.first(); + } + return getDomainMap().getDomainType(domainName, version); + } + + + public void addFromNode(Node amqpNode, AmqpVersion version) + { + // 1c. Extract domains + getConstantSet().addFromNode(amqpNode, 0, version); + _versionToConstantSetMap.get(version).addFromNode(amqpNode, 0, version); + + // 1d. Extract domains + getDomainMap().addFromNode(amqpNode, 0, version); + _versionToDomainMapMap.get(version).addFromNode(amqpNode, 0, version); + + // 1e. Extract class/method/field heirarchy + getModel().addFromNode(amqpNode, 0, version); + _versionToModelMap.get(version).addFromNode(amqpNode, 0, version); + } + + + public String getOutputDirectory() + { + return _outputDirectory; + } + + public String prepareConstantName(String constantName) + { + return prepareDomainName(constantName); + } + + + public boolean isFixedSizeType(String type) + { + return FIXED_SIZE_TYPES.containsKey(type); + } + + + public int getTypeSize(String type) + { + return FIXED_SIZE_TYPES.get(type); + } + + + + // Model-level template processing + abstract protected void processModelTemplate(NamedTemplate template); + + // Class-level template processing + abstract protected void processClassTemplate(NamedTemplate template, AmqpClass thisClass); + + // Method-level template processing + abstract protected void processMethodTemplate(NamedTemplate template, AmqpClass thisClass, + AmqpMethod method); + + // Field-level template processing + abstract protected void processTemplate(NamedTemplate template, AmqpClass thisClass, + AmqpMethod method, AmqpField field, AmqpVersion version); + + abstract protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method, + AmqpField field, AmqpVersion version); + + abstract protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, + AmqpField field, AmqpVersion version); + + abstract protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpModel model, AmqpVersion version); + + abstract protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpClass thisClass); + + + abstract protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpFieldMap fieldMap, AmqpVersion version); + + abstract protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet); + + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/JavaGenerator.java b/java/common/gentools/src/org/apache/qpid/gentools/JavaGenerator.java new file mode 100644 index 0000000000..7730fca1bd --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/JavaGenerator.java @@ -0,0 +1,1826 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.io.File; +import java.util.Iterator; +import java.util.List; +import java.util.TreeMap; + +public class JavaGenerator extends Generator +{ + // TODO: Move this to parent class + protected static final int FIELD_NAME = 0; + protected static final int FIELD_CODE_TYPE = 1; + + private class DomainInfo + { + final public String type; + final public String size; + final public String encodingType; + final public String encodeExpression; + final public String decodeExpression; + + public DomainInfo(String domain, String size, String encodingType, String encodeExpression, String decodeExpression) + { + this.type = domain; + this.size = size; + this.encodeExpression = encodeExpression; + this.decodeExpression = decodeExpression; + this.encodingType = encodingType; + } + } + + private static TreeMap typeMap = new TreeMap(); + + // Methods used for generation of code snippets called from the field map parsers + + // Common methods + private final CommandGenerateMethod declarationGenerateMethod = new CommandGenerateMethod() + { + public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) + { + return generateFieldDeclaration(codeType, field, versionSet, indentSize, tabSize, notLast); + } + }; + + private MangledGenerateMethod mangledDeclarationGenerateMethod = new MangledGenerateMethod() + { + public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) + { + return generateMangledFieldDeclaration(field, indentSize, tabSize, notLast); + } + }; + + // Methods for MessageBody classes + private CommandGenerateMethod mbGetGenerateMethod = new CommandGenerateMethod() + { + public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) + { + return generateMbGetMethod(codeType, field, versionSet, indentSize, tabSize, notLast); //To change body of implemented methods use File | Settings | File Templates. + } + }; + + private MangledGenerateMethod mbMangledGetGenerateMethod = new MangledGenerateMethod() + { + public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) + { + return generateMbMangledGetMethod(field, indentSize, tabSize, notLast); + } + }; + private CommandGenerateMethod mbParamListGenerateMethod = new CommandGenerateMethod() + { + public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) + { + return generateMbParamList(codeType, field, versionSet, indentSize, tabSize, notLast); + } + }; + private CommandGenerateMethod mbPassedParamListGenerateMethod = new CommandGenerateMethod() + { + public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) + { + return generateMbPassedParamList(codeType, field, versionSet, indentSize, tabSize, notLast); + } + }; + private MangledGenerateMethod mbMangledParamListGenerateMethod = new MangledGenerateMethod() + { + public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) + { + return generateMbMangledParamList(field, indentSize, tabSize, notLast); + } + }; + private MangledGenerateMethod mbMangledPassedParamListGenerateMethod = new MangledGenerateMethod() + { + public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) + { + return generateMbMangledPassedParamList(field, indentSize, tabSize, notLast); + } + }; + private CommandGenerateMethod mbBodyInitGenerateMethod = new CommandGenerateMethod() + { + public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) + { + return generateMbBodyInit(codeType, field, versionSet, indentSize, tabSize, notLast); + } + }; + private MangledGenerateMethod mbMangledBodyInitGenerateMethod = new MangledGenerateMethod() + { + public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) + { + return generateMbMangledBodyInit(field, indentSize, tabSize, notLast); + } + }; + private GenerateMethod mbSizeGenerateMethod = new GenerateMethod() + { + public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) + { + return generateMbFieldSize(domainType, fieldName, ordinal, indentSize, tabSize); + } + }; + private BitFieldGenerateMethod mbBitSizeGenerateMethod = new BitFieldGenerateMethod() + { + public String generate(List bitFieldList, int ordinal, int indentSize, int tabSize) + { + return generateMbBitArrayFieldSize(bitFieldList, ordinal, indentSize, tabSize); + } + }; + private GenerateMethod mbEncodeGenerateMethod = new GenerateMethod() + { + public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) + { + return generateMbFieldEncode(domainType, fieldName, ordinal, indentSize, tabSize); + } + }; + private BitFieldGenerateMethod mbBitEncodeGenerateMethod = new BitFieldGenerateMethod() + { + public String generate(List bitFieldList, int ordinal, int indentSize, int tabSize) + { + return generateMbBitFieldEncode(bitFieldList, ordinal, indentSize, tabSize); + } + }; + private GenerateMethod mbDecodeGenerateMethod = new GenerateMethod() + { + public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) + { + return generateMbFieldDecode(domainType, fieldName, ordinal, indentSize, tabSize); + } + }; + private BitFieldGenerateMethod mbBitDecodeGenerateMethod = new BitFieldGenerateMethod() + { + public String generate(List bitFieldList, int ordinal, int indentSize, int tabSize) + { + return generateMbBitFieldDecode(bitFieldList, ordinal, indentSize, tabSize); + } + }; + private GenerateMethod mbToStringGenerateMethod = new GenerateMethod() + { + public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) + { + return generateMbFieldToString(domainType, fieldName, ordinal, indentSize, tabSize); + } + }; + private BitFieldGenerateMethod mbBitToStringGenerateMethod = new BitFieldGenerateMethod() + { + public String generate(List bitFieldList, int ordinal, int indentSize, int tabSize) + { + return generateMbBitFieldToString(bitFieldList, ordinal, indentSize, tabSize); + } + }; + + // Methods for PropertyContentHeader classes + private CommandGenerateMethod pchClearGenerateMethod = new CommandGenerateMethod() + { + public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) + { + return generatePchClearMethod(codeType, field, versionSet, indentSize, tabSize, notLast); + } + }; + private MangledGenerateMethod pchMangledClearGenerateMethod = new MangledGenerateMethod() + { + public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) + { + return generatePchMangledClearMethod(field, indentSize, tabSize, notLast); + } + }; + private CommandGenerateMethod pchGetGenerateMethod = new CommandGenerateMethod() + { + public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) + { + return generatePchGetMethod(codeType, field, versionSet, indentSize, tabSize, notLast); + } + }; + private MangledGenerateMethod pchMangledGetGenerateMethod = new MangledGenerateMethod() + { + public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) + { + return generatePchMangledGetMethod(field, indentSize, tabSize, notLast); + } + }; + private CommandGenerateMethod pchSetGenerateMethod = new CommandGenerateMethod() + { + public String generate(String codeType, AmqpField field, AmqpVersionSet versionSet, int indentSize, int tabSize, boolean notLast) + { + return generatePchSetMethod(codeType, field, versionSet, indentSize, tabSize, notLast); + } + }; + private MangledGenerateMethod pchMangledSetGenerateMethod = new MangledGenerateMethod() + { + public String generate(AmqpField field, int indentSize, int tabSize, boolean notLast) + { + return generatePchMangledSetMethod(field, indentSize, tabSize, notLast); + } + }; + private GenerateMethod pchSizeGenerateMethod = new GenerateMethod() + { + public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) + { + return generatePchFieldSize(domainType, fieldName, ordinal, indentSize, tabSize); + } + }; + private BitFieldGenerateMethod pchBitSizeGenerateMethod = new BitFieldGenerateMethod() + { + public String generate(List bitFieldList, int ordinal, int indentSize, int tabSize) + { + return generatePchBitArrayFieldSize(bitFieldList, ordinal, indentSize, tabSize); + } + }; + private GenerateMethod pchEncodeGenerateMethod = new GenerateMethod() + { + public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) + { + return generatePchFieldEncode(domainType, fieldName, ordinal, indentSize, tabSize); + } + }; + private BitFieldGenerateMethod pchBitEncodeGenerateMethod = new BitFieldGenerateMethod() + { + public String generate(List bitFieldList, int ordinal, int indentSize, int tabSize) + { + return generatePchBitFieldEncode(bitFieldList, ordinal, indentSize, tabSize); + } + }; + private GenerateMethod pchDecodeGenerateMethod = new GenerateMethod() + { + public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) + { + return generatePchFieldDecode(domainType, fieldName, ordinal, indentSize, tabSize); + } + }; + private BitFieldGenerateMethod pchBitDecodeGenerateMethod = new BitFieldGenerateMethod() + { + public String generate(List bitFieldList, int ordinal, int indentSize, int tabSize) + { + return generatePchBitFieldDecode(bitFieldList, ordinal, indentSize, tabSize); + } + }; + private GenerateMethod pchGetPropertyFlagsGenerateMethod = new GenerateMethod() + { + public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) + { + return generatePchGetPropertyFlags(domainType, fieldName, ordinal, indentSize, tabSize); + } + }; + private BitFieldGenerateMethod pchBitGetPropertyFlagsGenerateMethod = new BitFieldGenerateMethod() + { + public String generate(List bitFieldList, int ordinal, int indentSize, int tabSize) + { + return generatePchBitGetPropertyFlags(bitFieldList, ordinal, indentSize, tabSize); + } + }; + private GenerateMethod pchSetPropertyFlagsGenerateMethod = new GenerateMethod() + { + public String generate(String domainType, String fieldName, int ordinal, int indentSize, int tabSize) + { + return generatePchSetPropertyFlags(domainType, fieldName, ordinal, indentSize, tabSize); + } + }; + private BitFieldGenerateMethod pchBitSetPropertyFlagsGenerateMethod = new BitFieldGenerateMethod() + { + public String generate(List bitFieldList, int ordinal, int indentSize, int tabSize) + { + return generatePchBitSetPropertyFlags(bitFieldList, ordinal, indentSize, tabSize); + } + }; + + + public String getNativeType(String type) + { + return typeMap.get(type).type; + } + + public String getEncodingType(String type) + { + return typeMap.get(type).encodingType; + } + + + public JavaGenerator() + { + super(); + // Load Java type and size maps. + // Adjust or add to these lists as new types are added/defined. + // The char '#' will be replaced by the field variable name (any type). + // The char '~' will be replaced by the compacted bit array size (type bit only). + typeMap.put("bit", new DomainInfo( + "boolean", // Java code type + "~", // size + "Boolean", // Java code type + "EncodingUtils.writeBooleans(buffer, #)", // encode expression + "# = EncodingUtils.readBooleans(buffer)")); // decode expression + typeMap.put("bitfield", new DomainInfo( + "byte", // Java code type + "~", // size + "Bitfield", + "EncodingUtils.writeBooleans(buffer, #)", // encode expression + "# = EncodingUtils.readBooleans(buffer)")); // decode expression + + typeMap.put("content", new DomainInfo( + "Content", // Java code type + "EncodingUtils.encodedContentLength(#)", // size + "Content", // Java code type + "EncodingUtils.writeContentBytes(buffer, #)", // encode expression + "# = EncodingUtils.readContent(buffer)")); // decode expression + typeMap.put("long", new DomainInfo( + "long", // Java code type + "4", // size + "UnsignedInteger", // Java code type + "EncodingUtils.writeUnsignedInteger(buffer, #)", // encode expression + "# = buffer.getUnsignedInt()")); // decode expression + typeMap.put("longlong", new DomainInfo( + "long", // Java code type + "8", // size + "Long", + "buffer.putLong(#)", // encode expression + "# = buffer.getLong()")); // decode expression + typeMap.put("longstr", new DomainInfo( + "byte[]", // Java code type + "EncodingUtils.encodedLongstrLength(#)", // size + "Bytes", + "EncodingUtils.writeLongStringBytes(buffer, #)", // encode expression + "# = EncodingUtils.readLongstr(buffer)")); // decode expression + typeMap.put("octet", new DomainInfo( + "short", // Java code type + "1", // size + "UnsignedByte", + "EncodingUtils.writeUnsignedByte(buffer, #)", // encode expression + "# = buffer.getUnsigned()")); // decode expression + typeMap.put("short", new DomainInfo( + "int", // Java code type + "2", // size + "UnsignedShort", + "EncodingUtils.writeUnsignedShort(buffer, #)", // encode expression + "# = buffer.getUnsignedShort()")); // decode expression + typeMap.put("shortstr", new DomainInfo( + "AMQShortString", // Java code type + "EncodingUtils.encodedShortStringLength(#)", // size + "AMQShortString", // Java code type + "EncodingUtils.writeShortStringBytes(buffer, #)", // encode expression + "# = EncodingUtils.readAMQShortString(buffer)")); // decode expression + typeMap.put("table", new DomainInfo( + "FieldTable", // Java code type + "EncodingUtils.encodedFieldTableLength(#)", // size + "FieldTable", // Java code type + "EncodingUtils.writeFieldTableBytes(buffer, #)", // encode expression + "# = EncodingUtils.readFieldTable(buffer)")); // decode expression + typeMap.put("timestamp", new DomainInfo( + "long", // Java code type + "8", // size + "Timestamp", + "EncodingUtils.writeTimestamp(buffer, #)", // encode expression + "# = EncodingUtils.readTimestamp(buffer)")); // decode expression + } + + // === Start of methods for Interface LanguageConverter === + + public String prepareClassName(String className) + { + return camelCaseName(className, true); + } + + public String prepareMethodName(String methodName) + { + return camelCaseName(methodName, false); + } + + public String prepareDomainName(String domainName) + { + return camelCaseName(domainName, false); + } + + + public String getGeneratedType(String domainName, AmqpVersion version) + { + String domainType = getDomainType(domainName, version); + if (domainType == null) + { + throw new AmqpTypeMappingException("Domain type \"" + domainName + + "\" not found in Java typemap."); + } + DomainInfo info = typeMap.get(domainType); + if (info == null) + { + throw new AmqpTypeMappingException("Unknown domain: \"" + domainType + "\""); + } + return info.type; + } + + // === Abstract methods from class Generator - Java-specific implementations === + + @Override + protected String prepareFilename(String filenameTemplate, AmqpClass thisClass, AmqpMethod method, + AmqpField field, AmqpVersion version) + { + StringBuffer sb = new StringBuffer(filenameTemplate); + if (thisClass != null) + { + replaceToken(sb, "${CLASS}", thisClass.getName()); + } + if (method != null) + { + replaceToken(sb, "${METHOD}", method.getName()); + } + if (field != null) + { + replaceToken(sb, "${FIELD}", field.getName()); + } + if (version != null) + { + replaceToken(sb, "${MAJOR}", String.valueOf(version.getMajor())); + replaceToken(sb, "${MINOR}", String.valueOf(version.getMinor())); + } + return sb.toString(); + } + + @Override + protected void processModelTemplate(NamedTemplate template) + { + processTemplate(template, null, null, null, null); + } + + @Override + protected void processClassTemplate(NamedTemplate template, AmqpClass thisClass) + { + processTemplate(template, thisClass, null, null, + thisClass.getVersionSet().size() == 1 ? thisClass.getVersionSet().first() : null); + } + + @Override + protected void processMethodTemplate(NamedTemplate template, AmqpClass thisClass, + AmqpMethod method) + { + processTemplate(template, thisClass, method, null, + thisClass.getVersionSet().size() == 1 ? thisClass.getVersionSet().first() : null); + } + + protected void processFieldTemplate(NamedTemplate template, AmqpClass thisClass, + AmqpMethod method, AmqpField field) + { + processTemplate(template, thisClass, method, field, + thisClass.getVersionSet().size() == 1 ? thisClass.getVersionSet().first() : null); + } + + @Override + protected void processTemplate(NamedTemplate template, AmqpClass thisClass, + AmqpMethod method, AmqpField field, AmqpVersion version) + { + StringBuffer sb = new StringBuffer(template.getTemplate()); + String filename = prepareFilename(getTemplateFileName(sb), thisClass, method, field, version); + processTemplate(sb, thisClass, method, field, template.getName(), version); + writeTargetFile(sb, new File(getOutputDirectory() + Utils.FILE_SEPARATOR + filename)); + generatedFileCounter++; + } + + protected void processTemplate(StringBuffer sb, AmqpClass thisClass, AmqpMethod method, + AmqpField field, String templateFileName, AmqpVersion version) + { + try + { + processAllLists(sb, thisClass, method, version); + } + catch (AmqpTemplateException e) + { + System.out.println("WARNING: " + templateFileName + ": " + e.getMessage()); + } + try + { + processAllTokens(sb, thisClass, method, field, version); + } + catch (AmqpTemplateException e) + { + System.out.println("WARNING: " + templateFileName + ": " + e.getMessage()); + } + } + + @Override + protected String processToken(String token, AmqpClass thisClass, AmqpMethod method, AmqpField field, + AmqpVersion version) + { + if (token.compareTo("${GENERATOR}") == 0) + { + return GENERATOR_INFO; + } + if (token.compareTo("${CLASS}") == 0 && thisClass != null) + { + return thisClass.getName(); + } + if (token.compareTo("${CLASS_ID_INIT}") == 0 && thisClass != null) + { + return generateIndexInitializer("registerClassId", thisClass.getIndexMap(), 8); + } + if (token.compareTo("${METHOD}") == 0 && method != null) + { + return method.getName(); + } + if (token.compareTo("${METHOD_ID_INIT}") == 0 && method != null) + { + return generateIndexInitializer("registerMethodId", method.getIndexMap(), 8); + } + if (token.compareTo("${FIELD}") == 0 && field != null) + { + return field.getName(); + } + + // This token is used only with class or method-level templates + if (token.compareTo("${pch_property_flags_declare}") == 0) + { + return generatePchPropertyFlagsDeclare(); + } + else if (token.compareTo("${pch_property_flags_initializer}") == 0) + { + int mapSize = method == null ? thisClass.getFieldMap().size() : method.getFieldMap().size(); + return generatePchPropertyFlagsInitializer(mapSize); + } + else if (token.compareTo("${pch_compact_property_flags_initializer}") == 0) + { + return generatePchCompactPropertyFlagsInitializer(thisClass, 8, 4); + } + else if (token.compareTo("${pch_compact_property_flags_check}") == 0) + { + return generatePchCompactPropertyFlagsCheck(thisClass, 8, 4); + } + + // Oops! + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + + @Override + protected void processClassList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpModel model, AmqpVersion version) + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${reg_map_put_method}") == 0) + { + codeSnippet = generateRegistry(model, 8, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processMethodList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpClass thisClass) + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + //TODO - we don't have any cases of this (yet). + if (token.compareTo("${???}") == 0) + { + codeSnippet = token; + } + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processFieldList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpFieldMap fieldMap, AmqpVersion version) + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + // Field declarations - common to MethodBody and PropertyContentHeader classes + if (token.compareTo("${field_declaration}") == 0) + { + codeSnippet = fieldMap.parseFieldMap(declarationGenerateMethod, + mangledDeclarationGenerateMethod, 4, 4, this); + } + + // MethodBody classes + else if (token.compareTo("${mb_field_get_method}") == 0) + { + codeSnippet = fieldMap.parseFieldMap(mbGetGenerateMethod, + mbMangledGetGenerateMethod, 4, 4, this); + } + else if (token.compareTo("${mb_field_parameter_list}") == 0) + { + // The code generated by this is ugly... It puts a comma on a line by itself! + // TODO: Find a more elegant solution here sometime... + codeSnippet = fieldMap.size() > 0 ? Utils.createSpaces(42) + "," + CR : ""; + // + codeSnippet += fieldMap.parseFieldMap(mbParamListGenerateMethod, + mbMangledParamListGenerateMethod, 42, 4, this); + } + + else if (token.compareTo("${mb_field_passed_parameter_list}") == 0) + { + // The code generated by this is ugly... It puts a comma on a line by itself! + // TODO: Find a more elegant solution here sometime... + codeSnippet = fieldMap.size() > 0 ? Utils.createSpaces(42) + "," + CR : ""; + // + codeSnippet += fieldMap.parseFieldMap(mbPassedParamListGenerateMethod, + mbMangledPassedParamListGenerateMethod, 42, 4, this); + } + else if (token.compareTo("${mb_field_body_initialize}") == 0) + { + codeSnippet = fieldMap.parseFieldMap(mbBodyInitGenerateMethod, + mbMangledBodyInitGenerateMethod, 8, 4, this); + } + else if (token.compareTo("${mb_field_size}") == 0) + { + codeSnippet = fieldMap.parseFieldMapOrdinally(mbSizeGenerateMethod, + mbBitSizeGenerateMethod, 8, 4, this); + } + else if (token.compareTo("${mb_field_encode}") == 0) + { + codeSnippet = fieldMap.parseFieldMapOrdinally(mbEncodeGenerateMethod, + mbBitEncodeGenerateMethod, 8, 4, this); + } + else if (token.compareTo("${mb_field_decode}") == 0) + { + codeSnippet = fieldMap.parseFieldMapOrdinally(mbDecodeGenerateMethod, + mbBitDecodeGenerateMethod, 8, 4, this); + } + else if (token.compareTo("${mb_field_to_string}") == 0) + { + codeSnippet = fieldMap.parseFieldMapOrdinally(mbToStringGenerateMethod, + mbBitToStringGenerateMethod, 8, 4, this); + } + + // PropertyContentHeader classes + else if (token.compareTo("${pch_field_list_size}") == 0) + { + codeSnippet = fieldMap.parseFieldMapOrdinally(pchSizeGenerateMethod, + pchBitSizeGenerateMethod, 12, 4, this); + } + else if (token.compareTo("${pch_field_list_payload}") == 0) + { + codeSnippet = fieldMap.parseFieldMapOrdinally(pchEncodeGenerateMethod, + pchBitEncodeGenerateMethod, 12, 4, this); + } + else if (token.compareTo("${pch_field_list_decode}") == 0) + { + codeSnippet = fieldMap.parseFieldMapOrdinally(pchDecodeGenerateMethod, + pchBitDecodeGenerateMethod, 12, 4, this); + } + else if (token.compareTo("${pch_get_compact_property_flags}") == 0) + { + codeSnippet = fieldMap.parseFieldMapOrdinally(pchGetPropertyFlagsGenerateMethod, + pchBitGetPropertyFlagsGenerateMethod, 8, 4, this); + } + else if (token.compareTo("${pch_set_compact_property_flags}") == 0) + { + codeSnippet = fieldMap.parseFieldMapOrdinally(pchSetPropertyFlagsGenerateMethod, + pchBitSetPropertyFlagsGenerateMethod, 8, 4, this); + } + else if (token.compareTo("${pch_field_clear_methods}") == 0) + { + codeSnippet = fieldMap.parseFieldMap(pchClearGenerateMethod, + pchMangledClearGenerateMethod, 4, 4, this); + } + else if (token.compareTo("${pch_field_get_methods}") == 0) + { + codeSnippet = fieldMap.parseFieldMap(pchGetGenerateMethod, + pchMangledGetGenerateMethod, 4, 4, this); + } + else if (token.compareTo("${pch_field_set_methods}") == 0) + { + codeSnippet = fieldMap.parseFieldMap(pchSetGenerateMethod, + pchMangledSetGenerateMethod, 4, 4, this); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + sb.insert(listMarkerStartIndex, codeSnippet); + } + + @Override + protected void processConstantList(StringBuffer sb, int listMarkerStartIndex, int listMarkerEndIndex, + AmqpConstantSet constantSet) + { + String codeSnippet; + int lend = sb.indexOf(CR, listMarkerStartIndex) + 1; // Include cr at end of line + String tline = sb.substring(listMarkerEndIndex, lend); // Line excluding line marker, including cr + int tokStart = tline.indexOf('$'); + String token = tline.substring(tokStart).trim(); + sb.delete(listMarkerStartIndex, lend); + + if (token.compareTo("${const_get_method}") == 0) + { + codeSnippet = generateConstantGetMethods(constantSet, 4, 4); + } + + else // Oops! + { + throw new AmqpTemplateException("Template token " + token + " unknown."); + } + + sb.insert(listMarkerStartIndex, codeSnippet); + } + + // === Protected and private helper functions unique to Java implementation === + + // Methods used for generation of code snippets called from the field map parsers + + // Common methods + + protected String generateFieldDeclaration(String codeType, AmqpField field, + AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) + { + return Utils.createSpaces(indentSize) + "public " + codeType + " " + field.getName() + + "; // AMQP version(s): " + versionSet + CR; + } + + protected String generateMangledFieldDeclaration(AmqpField field, int indentSize, + int tabSize, boolean nextFlag) + { + StringBuffer sb = new StringBuffer(); + Iterator dItr = field.getDomainMap().keySet().iterator(); + int domainCntr = 0; + while (dItr.hasNext()) + { + String domainName = dItr.next(); + AmqpVersionSet versionSet = field.getDomainMap().get(domainName); + String codeType = getGeneratedType(domainName, versionSet.first()); + sb.append(Utils.createSpaces(indentSize) + "public " + codeType + " " + + field.getName() + "_" + (domainCntr++) + "; // AMQP Version(s): " + versionSet + + CR); + } + return sb.toString(); + } + + protected String generateIndexInitializer(String mapName, AmqpOrdinalVersionMap indexMap, int indentSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + Iterator iItr = indexMap.keySet().iterator(); + while (iItr.hasNext()) + { + int index = iItr.next(); + AmqpVersionSet versionSet = indexMap.get(index); + Iterator vItr = versionSet.iterator(); + while (vItr.hasNext()) + { + AmqpVersion version = vItr.next(); + sb.append(indent + mapName + "( (byte) " + version.getMajor() + ", (byte) " + version.getMinor() + ", " + index + ");" + CR); + } + } + return sb.toString(); + } + + protected String generateRegistry(AmqpModel model, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + + for (String className : model.getClassMap().keySet()) + { + AmqpClass thisClass = model.getClassMap().get(className); + for (String methodName : thisClass.getMethodMap().keySet()) + { + AmqpMethod method = thisClass.getMethodMap().get(methodName); + for (AmqpVersion version : model.getVersionSet()) + { + // Find class and method index for this version (if it exists) + try + { + int classIndex = findIndex(thisClass.getIndexMap(), version); + int methodIndex = findIndex(method.getIndexMap(), version); + sb.append(indent + "registerMethod(" + CR); + sb.append(indent + tab + "(short)" + classIndex + + ", (short)" + methodIndex + ", (byte)" + version.getMajor() + + ", (byte)" + version.getMinor() + ", " + CR); + sb.append(indent + tab + Utils.firstUpper(thisClass.getName()) + + Utils.firstUpper(method.getName()) + "Body.getFactory());" + CR); + } + catch (Exception e) + { + } // Ignore + } + } + } + return sb.toString(); + } + + protected int findIndex(TreeMap map, AmqpVersion version) + { + Iterator iItr = map.keySet().iterator(); + while (iItr.hasNext()) + { + int index = iItr.next(); + AmqpVersionSet versionSet = map.get(index); + if (versionSet.contains(version)) + { + return index; + } + } + throw new IllegalArgumentException("Index not found"); + } + + // Methods for AmqpConstants class + + + public String prepareConstantName(String constantName) + { + return upperCaseName(constantName); + } + + + protected String generateConstantGetMethods(AmqpConstantSet constantSet, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + + for (AmqpConstant constant : constantSet.getContstants()) + { + + if (constant.isVersionConsistent(constantSet.getVersionSet())) + { + // return a constant + String value = constant.firstKey(); + if (Utils.containsOnlyDigits(value)) + { + sb.append(indent + "public static final int " + constant.getName() + " = " + + constant.firstKey() + ";" + CR); + } + else if (Utils.containsOnlyDigitsAndDecimal(value)) + { + sb.append(indent + "public static double " + constant.getName() + " = " + + constant.firstKey() + "; " + CR); + } + else + { + sb.append(indent + "public static String " + constant.getName() + " = " + + constant.firstKey() + "\"; " + CR); + + } + sb.append(CR); + } + else + { + // Return version-specific constant + sb.append(generateVersionDependentGet(constant, "String", "", "\"", "\"", indentSize, tabSize)); + sb.append(generateVersionDependentGet(constant, "int", "AsInt", "", "", indentSize, tabSize)); + sb.append(generateVersionDependentGet(constant, "double", "AsDouble", "(double)", "", indentSize, tabSize)); + sb.append(CR); + } + } + return sb.toString(); + } + + protected String generateVersionDependentGet(AmqpConstant constant, + String methodReturnType, String methodNameSuffix, String returnPrefix, String returnPostfix, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "public static " + methodReturnType + " " + constant.getName() + + methodNameSuffix + "(byte major, byte minor) throws AMQProtocolVersionException" + CR); + sb.append(indent + "{" + CR); + boolean first = true; + Iterator sItr = constant.keySet().iterator(); + while (sItr.hasNext()) + { + String value = sItr.next(); + AmqpVersionSet versionSet = constant.get(value); + sb.append(indent + tab + (first ? "" : "else ") + "if (" + generateVersionCheck(versionSet) + + ")" + CR); + sb.append(indent + tab + "{" + CR); + if (methodReturnType.compareTo("int") == 0 && !Utils.containsOnlyDigits(value)) + { + sb.append(generateConstantDeclarationException(constant.getName(), methodReturnType, + indentSize + (2 * tabSize), tabSize)); + } + else if (methodReturnType.compareTo("double") == 0 && !Utils.containsOnlyDigitsAndDecimal(value)) + { + sb.append(generateConstantDeclarationException(constant.getName(), methodReturnType, + indentSize + (2 * tabSize), tabSize)); + } + else + { + sb.append(indent + tab + tab + "return " + returnPrefix + value + returnPostfix + ";" + CR); + } + sb.append(indent + tab + "}" + CR); + first = false; + } + sb.append(indent + tab + "else" + CR); + sb.append(indent + tab + "{" + CR); + sb.append(indent + tab + tab + "throw new AMQProtocolVersionException(\"Constant \\\"" + + constant.getName() + "\\\" \" +" + CR); + sb.append(indent + tab + tab + tab + + "\"is undefined for AMQP version \" + major + \"-\" + minor + \".\");" + CR); + sb.append(indent + tab + "}" + CR); + sb.append(indent + "}" + CR); + return sb.toString(); + } + + protected String generateConstantDeclarationException(String name, String methodReturnType, + int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "throw new AMQProtocolVersionException(\"Constant \\\"" + + name + "\\\" \" +" + CR); + sb.append(indent + tab + "\"cannot be converted to type " + methodReturnType + + " for AMQP version \" + major + \"-\" + minor + \".\");" + CR); + return sb.toString(); + } + + // Methods for MessageBody classes + protected String generateMbGetMethod(String codeType, AmqpField field, + AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) + { + return Utils.createSpaces(indentSize) + "public " + codeType + " get" + + Utils.firstUpper(field.getName()) + "() { return " + field.getName() + "; }" + + CR; + } + + protected String generateMbMangledGetMethod(AmqpField field, int indentSize, + int tabSize, boolean nextFlag) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(CR); + sb.append(indent + "public T get" + Utils.firstUpper(field.getName()) + + "(Class classObj) throws AMQProtocolVersionException" + CR); + sb.append(indent + "{" + CR); + Iterator dItr = field.getDomainMap().keySet().iterator(); + int domainCntr = 0; + while (dItr.hasNext()) + { + String domainName = dItr.next(); + AmqpVersionSet versionSet = field.getDomainMap().get(domainName); + String codeType = getGeneratedType(domainName, versionSet.first()); + sb.append(indent + tab + "if (classObj.equals(" + codeType + + ".class)) // AMQP Version(s): " + versionSet + CR); + sb.append(indent + tab + tab + "return (T)(Object)" + field.getName() + "_" + + (domainCntr++) + ";" + CR); + } + sb.append(indent + tab + + "throw new AMQProtocolVersionException(\"None of the AMQP versions defines \" +" + + CR + " \"field \\\"" + field.getName() + + "\\\" as domain \\\"\" + classObj.getName() + \"\\\".\");" + CR); + sb.append(indent + "}" + CR); + sb.append(CR); + return sb.toString(); + } + + protected String generateMbParamList(String codeType, AmqpField field, + AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) + { + return Utils.createSpaces(indentSize) + codeType + " " + field.getName() + + (nextFlag ? "," : "") + " // AMQP version(s): " + versionSet + CR; + } + + + protected String generateMbPassedParamList(String codeType, AmqpField field, + AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) + { + return Utils.createSpaces(indentSize) + field.getName() + + (nextFlag ? "," : "") + " // AMQP version(s): " + versionSet + CR; + } + + + protected String generateMbMangledParamList(AmqpField field, int indentSize, + int tabSize, boolean nextFlag) + { + StringBuffer sb = new StringBuffer(); + Iterator dItr = field.getDomainMap().keySet().iterator(); + int domainCntr = 0; + while (dItr.hasNext()) + { + String domainName = dItr.next(); + AmqpVersionSet versionSet = field.getDomainMap().get(domainName); + String codeType = getGeneratedType(domainName, versionSet.first()); + sb.append(Utils.createSpaces(indentSize) + codeType + " " + field.getName() + "_" + + (domainCntr++) + (nextFlag ? "," : "") + " // AMQP version(s): " + + versionSet + CR); + } + return sb.toString(); + } + + protected String generateMbMangledPassedParamList(AmqpField field, int indentSize, + int tabSize, boolean nextFlag) + { + StringBuffer sb = new StringBuffer(); + Iterator dItr = field.getDomainMap().keySet().iterator(); + int domainCntr = 0; + while (dItr.hasNext()) + { + String domainName = dItr.next(); + AmqpVersionSet versionSet = field.getDomainMap().get(domainName); + sb.append(Utils.createSpaces(indentSize) + field.getName() + "_" + + (domainCntr++) + (nextFlag ? "," : "") + " // AMQP version(s): " + + versionSet + CR); + } + return sb.toString(); + } + + + protected String generateMbBodyInit(String codeType, AmqpField field, + AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) + { + return Utils.createSpaces(indentSize) + "this." + field.getName() + " = " + field.getName() + + ";" + CR; + } + + protected String generateMbMangledBodyInit(AmqpField field, int indentSize, + int tabSize, boolean nextFlag) + { + StringBuffer sb = new StringBuffer(); + Iterator dItr = field.getDomainMap().keySet().iterator(); + int domainCntr = 0; + while (dItr.hasNext()) + { + dItr.next(); + sb.append(Utils.createSpaces(indentSize) + "this." + field.getName() + "_" + domainCntr + + " = " + field.getName() + "_" + (domainCntr++) + ";" + CR); + } + return sb.toString(); + } + + protected String generateMbFieldSize(String domainType, String fieldName, + int ordinal, int indentSize, int tabSize) + { + StringBuffer sb = new StringBuffer(); + sb.append(Utils.createSpaces(indentSize) + "size += " + + typeMap.get(domainType).size.replaceAll("#", fieldName) + + "; // " + fieldName + ": " + domainType + CR); + return sb.toString(); + } + + protected String generateMbBitArrayFieldSize(List bitFieldList, + int ordinal, int indentSize, int tabSize) + { + StringBuffer sb = new StringBuffer(); + int numBytes = ((bitFieldList.size() - 1) / 8) + 1; + String comment = bitFieldList.size() == 1 ? + bitFieldList.get(0) + ": bit" : + "Combinded bits: " + bitFieldList; + sb.append(Utils.createSpaces(indentSize) + "size += " + + typeMap.get("bit").size.replaceAll("~", String.valueOf(numBytes)) + + "; // " + comment + CR); + return sb.toString(); + } + + protected String generateMbFieldEncode(String domain, String fieldName, + int ordinal, int indentSize, int tabSize) + { + StringBuffer sb = new StringBuffer(); + sb.append(Utils.createSpaces(indentSize) + + typeMap.get(domain).encodeExpression.replaceAll("#", fieldName) + + "; // " + fieldName + ": " + domain + CR); + return sb.toString(); + } + + protected String generateMbBitFieldEncode(List bitFieldList, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + + StringBuilder sb = new StringBuilder(); + int i = 0; + while (i < bitFieldList.size()) + { + + StringBuilder line = new StringBuilder(); + + for (int j = 0; i < bitFieldList.size() && j < 8; i++, j++) + { + if (j != 0) + { + line.append(", "); + } + line.append(bitFieldList.get(i)); + } + + sb.append(indent + + typeMap.get("bit").encodeExpression.replaceAll("#", line.toString()) + ";" + CR); + } + return sb.toString(); + } + + protected String generateMbFieldDecode(String domain, String fieldName, + int ordinal, int indentSize, int tabSize) + { + StringBuffer sb = new StringBuffer(); + sb.append(Utils.createSpaces(indentSize) + + typeMap.get(domain).decodeExpression.replaceAll("#", fieldName) + + "; // " + fieldName + ": " + domain + CR); + return sb.toString(); + } + + protected String generateMbBitFieldDecode(List bitFieldList, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + + StringBuilder sb = new StringBuilder(indent); + sb.append("byte packedValue;"); + sb.append(CR); + + // RG HERE! + + int i = 0; + while (i < bitFieldList.size()) + { + sb.append(indent + "packedValue = EncodingUtils.readByte(buffer);" + CR); + + for (int j = 0; i < bitFieldList.size() && j < 8; i++, j++) + { + sb.append(indent + bitFieldList.get(i) + " = ( packedValue & (byte) (1 << " + j + ") ) != 0;" + CR); + } + } + return sb.toString(); + } + + protected String generateMbFieldToString(String domain, String fieldName, + int ordinal, int indentSize, int tabSize) + { + StringBuffer sb = new StringBuffer(); + sb.append(Utils.createSpaces(indentSize) + + "buf.append(\" " + fieldName + ": \" + " + fieldName + ");" + CR); + return sb.toString(); + } + + protected String generateMbBitFieldToString(List bitFieldList, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < bitFieldList.size(); i++) + { + String bitFieldName = bitFieldList.get(i); + sb.append(indent + "buf.append(\" " + bitFieldName + ": \" + " + bitFieldName + + ");" + CR); + } + return sb.toString(); + } + + // Methods for PropertyContentHeader classes + + protected String generatePchClearMethod(String codeType, AmqpField field, + AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) + { + // This is one case where the ordinal info is the only significant factor, + // the domain info plays no part. Defer to the mangled version; the code would be + // identical anyway... + return generatePchMangledClearMethod(field, indentSize, tabSize, nextFlag); + } + + protected String generatePchMangledClearMethod(AmqpField field, int indentSize, + int tabSize, boolean nextFlag) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "public void clear" + Utils.firstUpper(field.getName()) + + "()" + CR); + sb.append(indent + "{" + CR); + + // If there is more than one ordinal for this field or the ordinal does not + // apply to all known versions, then we need to generate version checks so + // we know which fieldProperty to clear. + if (field.getOrdinalMap().size() == 1 && + field.getOrdinalMap().get(field.getOrdinalMap().firstKey()).size() == field.getVersionSet().size()) + { + int ordinal = field.getOrdinalMap().firstKey(); + sb.append(indent + tab + "clearEncodedForm();" + CR); + sb.append(indent + tab + "propertyFlags[" + ordinal + "] = false;" + CR); + } + else + { + Iterator oItr = field.getOrdinalMap().keySet().iterator(); + while (oItr.hasNext()) + { + int ordinal = oItr.next(); + AmqpVersionSet versionSet = field.getOrdinalMap().get(ordinal); + sb.append(indent + tab); + if (ordinal != field.getOrdinalMap().firstKey()) + { + sb.append("else "); + } + sb.append("if ("); + sb.append(generateVersionCheck(versionSet)); + sb.append(")" + CR); + sb.append(indent + tab + "{" + CR); + sb.append(indent + tab + tab + "clearEncodedForm();" + CR); + sb.append(indent + tab + tab + "propertyFlags[" + ordinal + "] = false;" + CR); + sb.append(indent + tab + "}" + CR); + } + } + sb.append(indent + "}" + CR); + sb.append(CR); + return sb.toString(); + } + + protected String generatePchGetMethod(String codeType, AmqpField field, + AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(indent + "public " + codeType + " get" + + Utils.firstUpper(field.getName()) + "()" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab + "decodeIfNecessary();" + CR); + sb.append(indent + tab + "return " + field.getName() + ";" + CR); + sb.append(indent + "}" + CR); + sb.append(CR); + return sb.toString(); + } + + protected String generatePchMangledGetMethod(AmqpField field, int indentSize, + int tabSize, boolean nextFlag) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(indent + "public T get" + + Utils.firstUpper(field.getName()) + + "(Class classObj) throws AMQProtocolVersionException" + CR); + sb.append(indent + "{" + CR); + Iterator dItr = field.getDomainMap().keySet().iterator(); + int domainCntr = 0; + while (dItr.hasNext()) + { + String domainName = dItr.next(); + AmqpVersionSet versionSet = field.getDomainMap().get(domainName); + String codeType = getGeneratedType(domainName, versionSet.first()); + sb.append(indent + tab + "if (classObj.equals(" + codeType + + ".class)) // AMQP Version(s): " + versionSet + CR); + sb.append(indent + tab + "{" + CR); + sb.append(indent + tab + tab + "decodeIfNecessary();" + CR); + sb.append(indent + tab + tab + "return (T)(Object)" + field.getName() + "_" + + (domainCntr++) + ";" + CR); + sb.append(indent + tab + "}" + CR); + } + sb.append(indent + tab + + "throw new AMQProtocolVersionException(\"None of the AMQP versions defines \" +" + + CR + " \"field \\\"" + field.getName() + + "\\\" as domain \\\"\" + classObj.getName() + \"\\\".\");" + CR); + sb.append(indent + "}" + CR); + sb.append(CR); + return sb.toString(); + } + + protected String generatePchSetMethod(String codeType, AmqpField field, + AmqpVersionSet versionSet, int indentSize, int tabSize, boolean nextFlag) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "public void set" + Utils.firstUpper(field.getName()) + + "(" + codeType + " " + field.getName() + ")" + CR); + sb.append(indent + "{" + CR); + + // If there is more than one ordinal for this field or the ordinal does not + // apply to all known versions, then we need to generate version checks so + // we know which fieldProperty to clear. + if (field.getOrdinalMap().size() == 1 && + field.getOrdinalMap().get(field.getOrdinalMap().firstKey()).size() == field.getVersionSet().size()) + { + int ordinal = field.getOrdinalMap().firstKey(); + sb.append(indent + tab + "clearEncodedForm();" + CR); + sb.append(indent + tab + "propertyFlags[" + ordinal + "] = true;" + CR); + sb.append(indent + tab + "this." + field.getName() + " = " + field.getName() + ";" + CR); + } + else + { + Iterator oItr = field.getOrdinalMap().keySet().iterator(); + while (oItr.hasNext()) + { + int ordinal = oItr.next(); + AmqpVersionSet oVersionSet = field.getOrdinalMap().get(ordinal); + sb.append(indent + tab); + if (ordinal != field.getOrdinalMap().firstKey()) + { + sb.append("else "); + } + sb.append("if ("); + sb.append(generateVersionCheck(oVersionSet)); + sb.append(")" + CR); + sb.append(indent + tab + "{" + CR); + sb.append(indent + tab + tab + "clearEncodedForm();" + CR); + sb.append(indent + tab + tab + "propertyFlags[" + ordinal + "] = true;" + CR); + sb.append(indent + tab + tab + "this." + field.getName() + " = " + field.getName() + ";" + CR); + sb.append(indent + tab + "}" + CR); + } + } + sb.append(indent + "}" + CR); + sb.append(CR); + return sb.toString(); + } + + protected String generatePchMangledSetMethod(AmqpField field, int indentSize, + int tabSize, boolean nextFlag) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + + Iterator dItr = field.getDomainMap().keySet().iterator(); + int domainCntr = 0; + while (dItr.hasNext()) + { + String domainName = dItr.next(); + AmqpVersionSet versionSet = field.getDomainMap().get(domainName); + String codeType = getGeneratedType(domainName, versionSet.first()); + + // Find ordinal with matching version + AmqpVersionSet commonVersionSet = new AmqpVersionSet(); + Iterator oItr = field.getOrdinalMap().keySet().iterator(); + while (oItr.hasNext()) + { + int ordinal = oItr.next(); + AmqpVersionSet oVersionSet = field.getOrdinalMap().get(ordinal); + Iterator vItr = oVersionSet.iterator(); + boolean first = true; + while (vItr.hasNext()) + { + AmqpVersion thisVersion = vItr.next(); + if (versionSet.contains(thisVersion)) + { + commonVersionSet.add(thisVersion); + } + } + if (!commonVersionSet.isEmpty()) + { + sb.append(indent + "public void set" + Utils.firstUpper(field.getName()) + + "(" + codeType + " " + field.getName() + ")" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab); + if (!first) + { + sb.append("else "); + } + sb.append("if ("); + sb.append(generateVersionCheck(commonVersionSet)); + sb.append(")" + CR); + sb.append(indent + tab + "{" + CR); + sb.append(indent + tab + tab + "clearEncodedForm();" + CR); + sb.append(indent + tab + tab + "propertyFlags[" + ordinal + "] = true;" + CR); + sb.append(indent + tab + tab + "this." + field.getName() + "_" + (domainCntr++) + + " = " + field.getName() + ";" + CR); + sb.append(indent + tab + "}" + CR); + sb.append(indent + "}" + CR); + sb.append(CR); + first = false; + } + } + } + return sb.toString(); + } + + protected String generatePchFieldSize(String domainType, String fieldName, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(indent + "if (propertyFlags[" + ordinal + "]) // " + + fieldName + ": " + domainType + CR); + sb.append(indent + Utils.createSpaces(tabSize) + "size += " + + typeMap.get(domainType).size.replaceAll("#", fieldName) + ";" + CR); + sb.append(CR); + return sb.toString(); + } + + protected String generatePchBitArrayFieldSize(List bitFieldList, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + String comment = bitFieldList.size() == 1 ? + bitFieldList.get(0) + ": bit" : + "Combinded bits: " + bitFieldList; + StringBuffer sb = new StringBuffer(); + + if (bitFieldList.size() == 1) // single bit + { + sb.append(indent + "if (propertyFlags[" + (ordinal - 1) + "]) // " + comment + CR); + sb.append(indent + tab + "size += " + + typeMap.get("bit").size.replaceAll("~", "1") + ";" + CR); + } + else // multiple bits - up to 8 are combined into one byte + { + String bitCntrName = "bitCntr_" + ordinal; + int startOrdinal = ordinal - bitFieldList.size(); + sb.append(indent + "// " + comment + CR); + sb.append(indent + "int " + bitCntrName + " = 0;" + CR); + sb.append(indent + "for (int i=" + startOrdinal + "; i<" + ordinal + "; i++)" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab + "if (propertyFlags[i])" + CR); + sb.append(indent + tab + tab + bitCntrName + "++;" + CR); + sb.append(indent + "}" + CR); + sb.append(indent + "size += " + + typeMap.get("bit").size.replaceAll("~", bitCntrName + + " > 0 ? ((" + bitCntrName + " - 1) / 8) + 1 : 0") + ";" + CR); + } + sb.append(CR); + return sb.toString(); + } + + protected String generatePchFieldEncode(String domainType, String fieldName, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "if (propertyFlags[" + ordinal + "]) // " + fieldName + ": " + + domainType + CR); + sb.append(indent + Utils.createSpaces(tabSize) + + typeMap.get(domainType).encodeExpression.replaceAll("#", fieldName) + ";" + CR); + sb.append(CR); + return sb.toString(); + } + + protected String generatePchBitFieldEncode(List bitFieldList, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + String comment = bitFieldList.size() == 1 ? + bitFieldList.get(0) + ": bit" : + "Combinded bits: " + bitFieldList; + StringBuffer sb = new StringBuffer(); + + if (bitFieldList.size() == 1) // single bit + { + sb.append(indent + "if (propertyFlags[" + (ordinal - 1) + "]) // " + + bitFieldList.get(0) + ": bit" + CR); + sb.append(indent + tab + typeMap.get("bit").encodeExpression.replaceAll("#", + "new boolean[] {" + bitFieldList.get(0) + "}") + ";" + CR); + } + else // multiple bits - up to 8 are combined into one byte + { + int startOrdinal = ordinal - bitFieldList.size(); + String bitCntrName = "bitCntr" + startOrdinal; + sb.append(indent + "// " + comment + CR); + sb.append(indent + "int " + bitCntrName + " = 0;" + CR); + sb.append(indent + "for (int i=" + startOrdinal + "; i<=" + (ordinal - 1) + "; i++)" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab + "if (propertyFlags[i])" + CR); + sb.append(indent + tab + tab + bitCntrName + "++;" + CR); + sb.append(indent + "}" + CR); + sb.append(indent + "if (" + bitCntrName + " > 0) // Are any of the property bits set?" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab + "boolean[] fullBitArray = new boolean[] { "); + for (int i = 0; i < bitFieldList.size(); i++) + { + if (i != 0) + { + sb.append(", "); + } + sb.append(bitFieldList.get(i)); + } + sb.append(" };" + CR); + sb.append(indent + tab + "boolean[] flaggedBitArray = new boolean[" + bitCntrName + + "];" + CR); + sb.append(indent + tab + bitCntrName + " = 0;" + CR); + sb.append(indent + tab + "for (int i=" + startOrdinal + "; i<=" + (ordinal - 1) + + "; i++)" + CR); + sb.append(indent + tab + "{" + CR); + sb.append(indent + tab + tab + "if (propertyFlags[i])" + CR); + sb.append(indent + tab + tab + tab + "flaggedBitArray[" + bitCntrName + + "++] = fullBitArray[i];" + CR); + sb.append(indent + tab + "}" + CR); + sb.append(indent + tab + typeMap.get("bit").encodeExpression.replaceAll("#", + "flaggedBitArray") + ";" + CR); + sb.append(indent + "}" + CR); + } + sb.append(CR); + return sb.toString(); + } + + protected String generatePchFieldDecode(String domainType, String fieldName, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + sb.append(indent + "if (propertyFlags[" + ordinal + "]) // " + fieldName + ": " + + domainType + CR); + sb.append(indent + Utils.createSpaces(tabSize) + + typeMap.get(domainType).decodeExpression.replaceAll("#", fieldName) + ";" + CR); + sb.append(CR); + return sb.toString(); + } + + protected String generatePchBitFieldDecode(List bitFieldList, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + String comment = bitFieldList.size() == 1 ? + bitFieldList.get(0) + ": bit" : + "Combinded bits: " + bitFieldList; + StringBuffer sb = new StringBuffer(); + + if (bitFieldList.size() == 1) // single bit + { + sb.append(indent + "if (propertyFlags[" + (ordinal - 1) + "]) // " + + bitFieldList.get(0) + ": bit" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab + typeMap.get("bit").decodeExpression.replaceAll("#", + "boolean[] flaggedBitArray") + ";" + CR); + sb.append(indent + tab + bitFieldList.get(0) + " = flaggedBitArray[0];" + CR); + sb.append(indent + "}" + CR); + } + else // multiple bits - up to 8 are combined into one byte + { + int startOrdinal = ordinal - bitFieldList.size(); + String bitCntr = "bitCntr" + startOrdinal; + sb.append(indent + "// " + comment + CR); + sb.append(indent + "int " + bitCntr + " = 0;" + CR); + sb.append(indent + "for (int i=" + startOrdinal + "; i<=" + (ordinal - 1) + "; i++)" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab + "if (propertyFlags[i])" + CR); + sb.append(indent + tab + tab + bitCntr + "++;" + CR); + sb.append(indent + "}" + CR); + sb.append(indent + "if (" + bitCntr + " > 0) // Are any of the property bits set?" + CR); + sb.append(indent + "{" + CR); + sb.append(indent + tab + typeMap.get("bit").decodeExpression.replaceAll("#", + "boolean[] flaggedBitArray") + ";" + CR); + sb.append(indent + tab + bitCntr + " = 0;" + CR); + for (int i = 0; i < bitFieldList.size(); i++) + { + sb.append(indent + tab + "if (propertyFlags[" + (startOrdinal + i) + "])" + CR); + sb.append(indent + tab + tab + bitFieldList.get(i) + " = flaggedBitArray[" + + bitCntr + "++];" + CR); + } + sb.append(indent + "}" + CR); + } + + sb.append(CR); + return sb.toString(); + } + + protected String generatePchGetPropertyFlags(String domainType, String fieldName, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + int word = ordinal / 15; + int bit = 15 - (ordinal % 15); + sb.append(indent + "if (propertyFlags[" + ordinal + "]) // " + fieldName + ": " + + domainType + CR); + sb.append(indent + tab + "compactPropertyFlags[" + word + "] |= (1 << " + + bit + ");" + CR); + sb.append(CR); + return sb.toString(); + } + + protected String generatePchBitGetPropertyFlags(List bitFieldList, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + int startOrdinal = ordinal - bitFieldList.size(); + + for (int i = 0; i < bitFieldList.size(); i++) + { + int thisOrdinal = startOrdinal + i; + int word = thisOrdinal / 15; + int bit = 15 - (thisOrdinal % 15); + sb.append(indent + "if (propertyFlags[" + thisOrdinal + "])" + CR); + sb.append(indent + tab + "compactPropertyFlags[" + word + + "] |= (1 << " + bit + ");" + CR); + } + + sb.append(CR); + return sb.toString(); + } + + protected String generatePchSetPropertyFlags(String domainType, String fieldName, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + int word = ordinal / 15; + int bit = 15 - (ordinal % 15); + sb.append(indent + "propertyFlags[" + ordinal + "] = (compactPropertyFlags[" + + word + "] & (1 << " + bit + ")) > 0;" + CR); + return sb.toString(); + } + + protected String generatePchBitSetPropertyFlags(List bitFieldList, + int ordinal, int indentSize, int tabSize) + { + String indent = Utils.createSpaces(indentSize); + StringBuffer sb = new StringBuffer(); + int startOrdinal = ordinal - bitFieldList.size(); + + for (int i = 0; i < bitFieldList.size(); i++) + { + int thisOrdinal = startOrdinal + i; + int word = thisOrdinal / 15; + int bit = 15 - (thisOrdinal % 15); + sb.append(indent + "propertyFlags[" + thisOrdinal + "] = (compactPropertyFlags[" + + word + "] & (1 << " + bit + ")) > 0;" + CR); + } + return sb.toString(); + } + + private String generatePchPropertyFlagsDeclare() + { + return "private boolean[] propertyFlags;"; + } + + private String generatePchPropertyFlagsInitializer(int totNumFields) + { + return "propertyFlags = new boolean[" + totNumFields + "];"; + } + + private String generatePchCompactPropertyFlagsInitializer(AmqpClass thisClass, int indentSize, + int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + Iterator vItr = thisClass.getVersionSet().iterator(); + while (vItr.hasNext()) + { + AmqpVersion version = vItr.next(); + int numBytes = ((thisClass.getFieldMap().getNumFields(version) - 1) / 15) + 1; + + sb.append(indent); + if (!version.equals(thisClass.getVersionSet().first())) + { + sb.append("else "); + } + sb.append("if ( major == " + version.getMajor() + " && minor == " + + version.getMinor() + " )" + CR); + sb.append(indent + tab + "compactPropertyFlags = new int[] { "); + for (int i = 0; i < numBytes; i++) + { + if (i != 0) + { + sb.append(", "); + } + sb.append(i < numBytes - 1 ? "1" : "0"); // Set the "continue" flag where required + } + sb.append(" };" + CR); + } + return sb.toString(); + } + + private String generatePchCompactPropertyFlagsCheck(AmqpClass thisClass, int indentSize, + int tabSize) + { + String indent = Utils.createSpaces(indentSize); + String tab = Utils.createSpaces(tabSize); + StringBuffer sb = new StringBuffer(); + Iterator vItr = thisClass.getVersionSet().iterator(); + while (vItr.hasNext()) + { + AmqpVersion version = vItr.next(); + int numFields = thisClass.getFieldMap().getNumFields(version); + int numBytes = ((numFields - 1) / 15) + 1; + + sb.append(indent); + if (!version.equals(thisClass.getVersionSet().first())) + { + sb.append("else "); + } + sb.append("if ( major == " + version.getMajor() + " && minor == " + + version.getMinor() + " && compactPropertyFlags.length != " + numBytes + " )" + CR); + sb.append(indent + tab + + "throw new AMQProtocolVersionException(\"Property flag array size mismatch:\" +" + CR); + sb.append(indent + tab + tab + "\"(Size found: \" + compactPropertyFlags.length +" + CR); + sb.append(indent + tab + tab + "\") Version " + version + " has " + numFields + + " fields which requires an int array of size " + numBytes + ".\");" + CR); + } + return sb.toString(); + } + + private String generateVersionCheck(AmqpVersionSet v) + { + StringBuffer sb = new StringBuffer(); + AmqpVersion[] versionArray = new AmqpVersion[v.size()]; + v.toArray(versionArray); + for (int i = 0; i < versionArray.length; i++) + { + if (i != 0) + { + sb.append(" || "); + } + if (versionArray.length > 1) + { + sb.append("("); + } + sb.append("major == (byte)" + versionArray[i].getMajor() + " && minor == (byte)" + + versionArray[i].getMinor()); + if (versionArray.length > 1) + { + sb.append(")"); + } + } + return sb.toString(); + } + + private String camelCaseName(String name, boolean upperFirstFlag) + { + StringBuffer ccn = new StringBuffer(); + String[] toks = name.split("[-_.\\ ]"); + for (int i = 0; i < toks.length; i++) + { + StringBuffer b = new StringBuffer(toks[i]); + if (upperFirstFlag || i > 0) + { + b.setCharAt(0, Character.toUpperCase(toks[i].charAt(0))); + } + ccn.append(b); + } + return ccn.toString(); + } + + + private String upperCaseName(String name) + { + StringBuffer ccn = new StringBuffer(); + String[] toks = name.split("[-_.\\ ]"); + for (int i = 0; i < toks.length; i++) + { + if (i != 0) + { + ccn.append('_'); + } + ccn.append(toks[i].toUpperCase()); + + + } + return ccn.toString(); + } + + + public static Factory _factoryInstance = new Factory() + { + + public JavaGenerator newInstance() + { + return new JavaGenerator(); + } + }; + + public static Factory getFactory() + { + return _factoryInstance; + } + + + void processModelTemplate(NamedTemplate template, AmqpVersion version) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + void processClassTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpVersion version) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + void processMethodTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpVersion version) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + void processFieldTemplate(NamedTemplate template, AmqpClass amqpClass, AmqpMethod amqpMethod, AmqpField amqpField, AmqpVersion version) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/LanguageConverter.java b/java/common/gentools/src/org/apache/qpid/gentools/LanguageConverter.java new file mode 100644 index 0000000000..5e692d86e7 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/LanguageConverter.java @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +public interface LanguageConverter +{ + +// public AmqpDomainMap getDomainMap(); +// public AmqpConstantSet getConstantSet(); +// public AmqpModel getModel(); + + // + public String prepareClassName(String className); + + public String prepareMethodName(String methodName); + + public String prepareDomainName(String domainName); + + public String getDomainType(String domainName, AmqpVersion version); + + public String getGeneratedType(String domainName, AmqpVersion version); + + public String prepareConstantName(String constantName); +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/Main.java b/java/common/gentools/src/org/apache/qpid/gentools/Main.java new file mode 100644 index 0000000000..c0584f7ca7 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/Main.java @@ -0,0 +1,301 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.apache.velocity.app.Velocity; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Properties; + +public class Main +{ + private static final String DEFAULT_OUTPUT_DIR = ".." + Utils.FILE_SEPARATOR + "gen"; + private static final String DEFAULT_TEMPLATE_DIR_BASE = ".." + Utils.FILE_SEPARATOR; + + private enum GeneratedLanguage + { + CPP(".cpp", CppGenerator.getFactory()), + DOTNET(".net", DotnetGenerator.getFactory()), + JAVA(".java", JavaGenerator.getFactory()); + + private final String _suffix; + private final Generator.Factory _factory; + + + private final String _defaultTemplateDirectory; + + GeneratedLanguage(String suffix, Generator.Factory factory) + { + _suffix = suffix; + _factory = factory; + _defaultTemplateDirectory = DEFAULT_TEMPLATE_DIR_BASE + "templ" + _suffix; + } + + public String getSuffix() + { + return _suffix; + } + + public Generator newGenerator() + { + return _factory.newInstance(); + } + + public String getDefaultTemplateDirectory() + { + return _defaultTemplateDirectory; + } + } + + private Generator generator; + + private String outDir; + private String tmplDir; + private GeneratedLanguage _generatorLang; + private ArrayList xmlFiles; + + public Main() + { + xmlFiles = new ArrayList(); + } + + public void run(String[] args) + throws Exception, + SAXException, + AmqpParseException, + AmqpTypeMappingException, + AmqpTemplateException, + TargetDirectoryException, + IllegalAccessException, + InvocationTargetException, ParserConfigurationException + { + + // 0. Initialize + outDir = DEFAULT_OUTPUT_DIR; + tmplDir = null; + _generatorLang = GeneratedLanguage.CPP; // Default generation language + xmlFiles.clear(); + processArgs(args); + + if (tmplDir == null) + { + tmplDir = _generatorLang.getDefaultTemplateDirectory(); + } + + + generator = _generatorLang.newGenerator(); + generator.setTemplateDirectory(tmplDir); + generator.setOutputDirectory(outDir); + + // 1. Suck in all the XML spec files provided on the command line + analyzeXML(); + + Properties p = new Properties(); + p.setProperty("file.resource.loader.path", tmplDir); + + Velocity.init(p); + + // 2. Load up all templates + generator.initializeTemplates(); + + // 3. Generate output + generator.generate(); + + System.out.println("Files generated: " + generator.getNumberGeneratedFiles()); + System.out.println("Done."); + } + + private void processArgs(String[] args) + { + // Crude but simple... + for (int i = 0; i < args.length; i++) + { + String arg = args[i]; + if (arg.charAt(0) == '-') + { + switch (arg.charAt(1)) + { + case'c': + case'C': + _generatorLang = GeneratedLanguage.CPP; + break; + case'j': + case'J': + _generatorLang = GeneratedLanguage.JAVA; + break; + case'n': + case'N': + _generatorLang = GeneratedLanguage.DOTNET; + break; + case'o': + case'O': + if (++i < args.length) + { + outDir = args[i]; + } + break; + case't': + case'T': + if (++i < args.length) + { + tmplDir = args[i]; + } + break; + } + } + else + { + xmlFiles.add(args[i]); + } + } + } + + private void analyzeXML() + throws IOException, SAXException, AmqpParseException, AmqpTypeMappingException, ParserConfigurationException + { + DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + + System.out.println("XML files: " + xmlFiles); + for (String filename : xmlFiles) + { + File f = new File(filename); + if (f.exists()) + { + // 1a. Initialize dom + System.out.print(" \"" + filename + "\":"); + Document doc = docBuilder.parse(new File(filename)); + Node amqpNode = Utils.findChild(doc, Utils.ELEMENT_AMQP); + + // 1b. Extract version (major and minor) from the XML file + int major = Utils.getNamedIntegerAttribute(amqpNode, Utils.ATTRIBUTE_MAJOR); + int minor = Utils.getNamedIntegerAttribute(amqpNode, Utils.ATTRIBUTE_MINOR); + AmqpVersion version = new AmqpVersion(major, minor); + System.out.println(" Found version " + version.toString() + "."); + generator.addVersion(version); + generator.addFromNode(amqpNode, version); + + + } + else + { + System.err.println("ERROR: AMQP XML file \"" + filename + "\" not found."); + } + } +// *** DEBUG INFO *** Uncomment bits from this block to see lots of stuff.... +// System.out.println(); +// System.out.println("*** Debug output ***"); +// System.out.println(); +// versionSet.print(System.out, 0, 2); // List of loaded versions +// System.out.println(); +// constants.print(System.out, 0, 2); // List of constants +// System.out.println(); +// domainMap.print(System.out, 0, 2); // List of domains +// System.out.println(); +// model.print(System.out, 0, 2); // Internal version map model +// System.out.println(); +// System.out.println("*** End debug output ***"); +// System.out.println(); + } + + public static void main(String[] args) + { + int exitCode = 1; + // TODO: This is a simple and klunky way of hangling command-line args, and could be improved upon. + if (args.length < 2) + { + usage(); + } + else + { + try + { + new Main().run(args); + exitCode = 0; + } + catch (IOException e) + { + e.printStackTrace(); + } + catch (ParserConfigurationException e) + { + e.printStackTrace(); + } + catch (SAXException e) + { + e.printStackTrace(); + } + catch (AmqpParseException e) + { + e.printStackTrace(); + } + catch (AmqpTypeMappingException e) + { + e.printStackTrace(); + } + catch (AmqpTemplateException e) + { + e.printStackTrace(); + } + catch (TargetDirectoryException e) + { + e.printStackTrace(); + } + catch (IllegalAccessException e) + { + e.printStackTrace(); + } + catch (InvocationTargetException e) + { + e.printStackTrace(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + System.exit(exitCode); + } + + public static void usage() + { + System.out.println("AMQP XML generator v.0.0"); + System.out.println("Usage: Main -c|-j [-o outDir] [-t tmplDir] XMLfile [XMLfile ...]"); + System.out.println(" where -c: Generate C++."); + System.out.println(" -j: Generate Java."); + System.out.println(" -n: Generate .NET."); + System.out.println(" -o outDir: Use outDir as the output dir (default=\"" + DEFAULT_OUTPUT_DIR + "\")."); + System.out.println(" -t tmplDir: Find templates in tmplDir."); + System.out.println(" Defaults: \"" + GeneratedLanguage.CPP.getDefaultTemplateDirectory() + "\" for C++;"); + System.out.println(" \"" + GeneratedLanguage.JAVA.getDefaultTemplateDirectory() + "\" for java.;"); + System.out.println(" \"" + GeneratedLanguage.DOTNET.getDefaultTemplateDirectory() + "\" for .NET."); + System.out.println(" XMLfile is a space-separated list of AMQP XML files to be parsed."); + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/MangledGenerateMethod.java b/java/common/gentools/src/org/apache/qpid/gentools/MangledGenerateMethod.java new file mode 100644 index 0000000000..ffeefed900 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/MangledGenerateMethod.java @@ -0,0 +1,26 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +public interface MangledGenerateMethod +{ + String generate(AmqpField field, int indentSize, int tabSize, boolean notLast); +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/NodeAware.java b/java/common/gentools/src/org/apache/qpid/gentools/NodeAware.java new file mode 100644 index 0000000000..f832da75ad --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/NodeAware.java @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.w3c.dom.Node; + +/** + * @author kpvdr + * Interface allowing the addition of elements from a node in the + * DOM of the AMQP specification. It is used by each of the model + * elements in a recursive fashion to build the model. + */ +public interface NodeAware +{ + /** + * Add a model element from the current DOM node. All model elements must implement + * this interface. If the node contains children that are also a part of the model, + * then this method is called on new instances of those model elements. + * + * @param n Node from which the current model element is to be added. + * @param o Ordinal value of the current model elemet. + * @param v Verion of the DOM from which the node comes. + * @throws AmqpParseException + * @throws AmqpTypeMappingException + * @returns true if a node was added, false if not + */ + public boolean addFromNode(Node n, int o, AmqpVersion v) + throws AmqpParseException, AmqpTypeMappingException; +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/Printable.java b/java/common/gentools/src/org/apache/qpid/gentools/Printable.java new file mode 100644 index 0000000000..aa13df7b68 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/Printable.java @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.io.PrintStream; + +public interface Printable +{ + public void print(PrintStream out, int marginSize, int tabSize); +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionClass.java b/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionClass.java new file mode 100644 index 0000000000..8e1af1c551 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionClass.java @@ -0,0 +1,103 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.Map; +import java.util.List; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map.Entry; + + +public class SingleVersionClass +{ + private final int _classId; + + + private final AmqpClass _amqpClass; + private final AmqpVersion _amqpVersion; + private final Generator _generator; + private final List _methodList = new ArrayList(); + + public SingleVersionClass(AmqpClass amqpClass, AmqpVersion amqpVersion, Generator generator) + { + _amqpClass = amqpClass; + _amqpVersion = amqpVersion; + _generator = generator; + + AmqpOrdinalVersionMap indexMap = amqpClass.getIndexMap(); + int classId = 0; + for(Entry entry : indexMap.entrySet()) + { + if(entry.getValue().contains(_amqpVersion)) + { + classId = entry.getKey(); + break; + } + } + _classId = classId; + + + Collection methods = _amqpClass.getMethodMap().values(); + + for(AmqpMethod amqpMethod : methods) + { + _methodList.add(new SingleVersionMethod(amqpMethod, _amqpVersion, _generator)); + + } + + Collections.sort(_methodList, new Comparator(){ + public int compare(SingleVersionMethod method1, SingleVersionMethod method2) + { + return method1.getMethodId() - method2.getMethodId(); + } + }); + + + } + + public int getClassId() + { + return _classId; + } + + public String getName() + { + return _amqpClass.getName(); + } + + + + + + public List getMethodList() + { + return _methodList; + } + + + public int getMaximumMethodId() + { + return _methodList.get(_methodList.size()-1).getMethodId(); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionField.java b/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionField.java new file mode 100644 index 0000000000..b795663d15 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionField.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.gentools; + + +public class SingleVersionField +{ + private final AmqpField _field; + private final AmqpVersion _amqpVersion; + private final Generator _generator; + + public SingleVersionField(AmqpField field, AmqpVersion amqpVersion, Generator generator) + { + _field = field; + _amqpVersion = amqpVersion; + _generator = generator; + } + + public String getName() + { + return _field.getName(); + } + + public String getDomain() + { + return _field.getDomain(_amqpVersion); + } + + + public String getDomainType() + { + return _generator.getDomainType(_field.getDomain(_amqpVersion),_amqpVersion); + } + + public String getNativeType() + { + return _generator.getNativeType(getDomainType()); + } + + public String getEncodingType() + { + return _generator.getEncodingType(getDomainType()); + } + + + public int getPosition() + { + return _field.getOrdinal(_amqpVersion); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionMethod.java b/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionMethod.java new file mode 100644 index 0000000000..59a6d9e28a --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionMethod.java @@ -0,0 +1,154 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.Map.Entry; +import java.util.Collection; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.HashMap; + +public class SingleVersionMethod +{ + private final AmqpMethod _amqpMethod; + private final AmqpVersion _amqpVersion; + private final int _methodId; + private final List _fieldList = new ArrayList(); + private final Generator _generator; + private final List _consolidatedFields = new ArrayList(); + private final Map _fieldNameToConsolidatedFieldMap = new HashMap(); + + + public SingleVersionMethod(AmqpMethod amqpMethod, AmqpVersion amqpVersion, Generator generator) + { + _amqpMethod = amqpMethod; + _amqpVersion = amqpVersion; + _generator = generator; + + AmqpOrdinalVersionMap indexMap = amqpMethod.getIndexMap(); + int methodId = 0; + for(Entry entry : indexMap.entrySet()) + { + if(entry.getValue().contains(_amqpVersion)) + { + methodId = entry.getKey(); + break; + } + } + _methodId = methodId; + + Collection fields = _amqpMethod.getFieldMap().values(); + + for(AmqpField field : fields) + { + _fieldList.add(new SingleVersionField(field, _amqpVersion, _generator)); + + } + + Collections.sort(_fieldList, new Comparator(){ + public int compare(SingleVersionField field1, SingleVersionField field2) + { + return field1.getPosition() - field2.getPosition(); + } + }); + + + + ConsolidatedField lastField = null; + int bitfieldNum = 0; + for(SingleVersionField field : _fieldList) + { + String domainType = field.getDomainType(); + if(!domainType.equals("bit")) + { + lastField = new ConsolidatedField(_generator, + field.getName(), + field.getDomainType()); + _consolidatedFields.add(lastField); + } + else if(lastField == null || !lastField.getType().equals("bitfield")) + { + lastField = new ConsolidatedField(_generator, + domainType.equals("bit") ? "bitfield"+bitfieldNum++ : field.getName(), + domainType.equals("bit") ? "bitfield" : field.getDomainType(), + field.getName()); + _consolidatedFields.add(lastField); + } + else + { + lastField.add(field.getName()); + } + _fieldNameToConsolidatedFieldMap.put(field.getName(), lastField); + + } + } + + public int getMethodId() + { + return _methodId; + } + + public String getName() + { + return _amqpMethod.getName(); + } + + public Collection getFieldList() + { + return Collections.unmodifiableCollection(_fieldList); + } + + public List getConsolidatedFields() + { + return _consolidatedFields; + } + + public String getConsolidatedFieldName(String fieldName) + { + return _fieldNameToConsolidatedFieldMap.get(fieldName).getName(); + } + + public boolean isConsolidated(String fieldName) + { + return _fieldNameToConsolidatedFieldMap.get(fieldName).isConsolidated(); + } + + public int getPositionInBitField(String fieldName) + { + return _fieldNameToConsolidatedFieldMap.get(fieldName).getPosition(fieldName); + } + + + public boolean isServerMethod() + { + return _amqpMethod.isServerMethod(_amqpVersion); + } + + + public boolean isClientMethod() + { + return _amqpMethod.isClientMethod(_amqpVersion); + } + +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionModel.java b/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionModel.java new file mode 100644 index 0000000000..22b416e45a --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/SingleVersionModel.java @@ -0,0 +1,71 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import java.util.Collection; +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + + +public class SingleVersionModel +{ + private final AmqpModel _amqpModel; + private final AmqpVersion _amqpVersion; + private final Generator _generator; + private final List _classList = new ArrayList(); + + public SingleVersionModel(AmqpModel amqpModel, AmqpVersion amqpVersion, Generator generator) + { + _amqpModel = amqpModel; + _amqpVersion = amqpVersion; + _generator = generator; + + + Collection originalClasses = _amqpModel.getClassMap().values(); + + for(AmqpClass amqpClass : originalClasses) + { + _classList.add(new SingleVersionClass(amqpClass, _amqpVersion, _generator)); + + } + + Collections.sort(_classList, new Comparator(){ + public int compare(SingleVersionClass amqpClass1, SingleVersionClass amqpClass2) + { + return amqpClass1.getClassId() - amqpClass2.getClassId(); + } + }); + + + } + + public Collection getClassList() + { + return Collections.unmodifiableCollection(_classList); + } + + public int getMaximumClassId() + { + return _classList.get(_classList.size()-1).getClassId(); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/TargetDirectoryException.java b/java/common/gentools/src/org/apache/qpid/gentools/TargetDirectoryException.java new file mode 100644 index 0000000000..39ce666288 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/TargetDirectoryException.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +@SuppressWarnings("serial") +public class TargetDirectoryException extends RuntimeException +{ + public TargetDirectoryException(String msg) + { + super(msg); + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/Utils.java b/java/common/gentools/src/org/apache/qpid/gentools/Utils.java new file mode 100644 index 0000000000..1cedaeea12 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/Utils.java @@ -0,0 +1,159 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +import org.w3c.dom.Attr; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class Utils +{ + public final static String FILE_SEPARATOR = System.getProperty("file.separator"); + public final static String LINE_SEPARATOR = System.getProperty("line.separator"); + + public final static String ATTRIBUTE_NAME = "name"; + public final static String ATTRIBUTE_MAJOR = "major"; + public final static String ATTRIBUTE_MINOR = "minor"; + public final static String ATTRIBUTE_INDEX = "index"; + public final static String ATTRIBUTE_LABEL = "label"; + public final static String ATTRIBUTE_SYNCHRONOUS = "synchronous"; + public final static String ATTRIBUTE_CONTENT = "content"; + public final static String ATTRIBUTE_HANDLER = "handler"; + public final static String ATTRIBUTE_DOMAIN = "domain"; + public final static String ATTRIBUTE_VALUE = "value"; + public final static String ATTRIBUTE_TYPE = "type"; // For compatibility with AMQP 8.0 + + public final static String ELEMENT_AMQP = "amqp"; + public final static String ELEMENT_CHASSIS = "chassis"; + public final static String ELEMENT_CLASS = "class"; + public final static String ELEMENT_CODEGEN = "codegen"; + public final static String ELEMENT_CONSTANT = "constant"; + public final static String ELEMENT_DOMAIN = "domain"; + public final static String ELEMENT_METHOD = "method"; + public final static String ELEMENT_FIELD = "field"; + public final static String ELEMENT_VERSION = "version"; + + // Attribute functions + + public static String getNamedAttribute(Node n, String attrName) throws AmqpParseException + { + NamedNodeMap nnm = n.getAttributes(); + if (nnm == null) + { + throw new AmqpParseException("Node \"" + n.getNodeName() + "\" has no attributes."); + } + Attr a = (Attr) nnm.getNamedItem(attrName); + if (a == null) + { + throw new AmqpParseException("Node \"" + n.getNodeName() + "\" has no attribute \"" + attrName + "\"."); + } + return a.getNodeValue(); + } + + public static int getNamedIntegerAttribute(Node n, String attrName) throws AmqpParseException + { + return Integer.parseInt(getNamedAttribute(n, attrName)); + } + + // Element functions + + public static Node findChild(Node n, String eltName) throws AmqpParseException + { + NodeList nl = n.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) + { + Node cn = nl.item(i); + if (cn.getNodeName().compareTo(eltName) == 0) + { + return cn; + } + } + throw new AmqpParseException("Node \"" + n.getNodeName() + + "\" does not contain child element \"" + eltName + "\"."); + } + + // String functions + + public static String firstUpper(String str) + { + if (!Character.isLetter(str.charAt(0)) || !Character.isLowerCase(str.charAt(0))) + { + return str; + } + StringBuffer sb = new StringBuffer(str); + sb.setCharAt(0, Character.toUpperCase(str.charAt(0))); + return sb.toString(); + } + + public static String firstLower(String str) + { + if (!Character.isUpperCase(str.charAt(0))) + { + return str; + } + StringBuffer sb = new StringBuffer(str); + sb.setCharAt(0, Character.toLowerCase(str.charAt(0))); + return sb.toString(); + } + + public static String createSpaces(int cnt) + { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < cnt; i++) + { + sb.append(' '); + } + return sb.toString(); + } + + public static boolean containsOnlyDigits(String str) + { + boolean foundNonDigit = false; + for (int i = 0; i < str.length() && !foundNonDigit; i++) + { + if (!Character.isDigit(str.charAt(i))) + { + foundNonDigit = true; + } + } + return !foundNonDigit; + } + + public static boolean containsOnlyDigitsAndDecimal(String str) + { + boolean foundNonDigit = false; + int decimalCntr = 0; + for (int i = 0; i < str.length() && !foundNonDigit && decimalCntr < 2; i++) + { + char ch = str.charAt(i); + if (!(Character.isDigit(ch) || ch == '.')) + { + foundNonDigit = true; + } + else if (ch == '.') + { + decimalCntr++; + } + } + return !foundNonDigit && decimalCntr < 2; + } +} diff --git a/java/common/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java b/java/common/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java new file mode 100644 index 0000000000..a9cdd56e88 --- /dev/null +++ b/java/common/gentools/src/org/apache/qpid/gentools/VersionConsistencyCheck.java @@ -0,0 +1,26 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.gentools; + +public interface VersionConsistencyCheck +{ + public boolean isVersionConsistent(AmqpVersionSet globalVersionSet); +} diff --git a/java/common/protocol-version.xml b/java/common/protocol-version.xml deleted file mode 100644 index 5435a0a582..0000000000 --- a/java/common/protocol-version.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/common/src/main/java/common.bnd b/java/common/src/main/java/common.bnd index b34f8deacc..84350fdc75 100755 --- a/java/common/src/main/java/common.bnd +++ b/java/common/src/main/java/common.bnd @@ -17,7 +17,7 @@ # under the License. # -ver: 0.19.0 +ver: 0.21.0 Bundle-SymbolicName: qpid-common Bundle-Version: ${ver} diff --git a/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java b/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java index 5268ce9bc2..7aa280ce02 100644 --- a/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java +++ b/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java @@ -87,6 +87,8 @@ public class ClientProperties public static final String USE_LEGACY_MAP_MESSAGE_FORMAT = "qpid.use_legacy_map_message"; + public static final String USE_LEGACY_STREAM_MESSAGE_FORMAT = "qpid.use_legacy_stream_message"; + public static final String AMQP_VERSION = "qpid.amqp.version"; public static final String QPID_VERIFY_CLIENT_ID = "qpid.verify_client_id"; @@ -190,6 +192,19 @@ public class ClientProperties */ public static final long DEFAULT_FLOW_CONTROL_WAIT_NOTIFY_PERIOD = 5000L; + /** + * System property to control whether the client will declare queues during + * consumer creation when using BindingURLs. + */ + public static final String QPID_DECLARE_QUEUES_PROP_NAME = "qpid.declare_queues"; + + /** + * System property to control whether the client will declare exchanges during + * producer/consumer creation when using BindingURLs. + */ + public static final String QPID_DECLARE_EXCHANGES_PROP_NAME = "qpid.declare_exchanges"; + public static final String VERIFY_QUEUE_ON_SEND = "qpid.verify_queue_on_send"; + private ClientProperties() { diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java index fdc71e31f9..1381390640 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java @@ -110,7 +110,7 @@ public final class AMQShortString implements CharSequence, Comparable() { - + @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > LOCAL_INTERN_CACHE_SIZE; @@ -845,22 +845,15 @@ public final class AMQShortString implements CharSequence, Comparable +public interface ProtocolEngine extends Receiver, TransportActivity { // Returns the remote address of the NetworkDriver SocketAddress getRemoteAddress(); @@ -56,6 +57,6 @@ public interface ProtocolEngine extends Receiver void readerIdle(); - public void setNetworkConnection(NetworkConnection network, Sender sender); + public void setNetworkConnection(NetworkConnection network, Sender sender); } \ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/transport/Connection.java b/java/common/src/main/java/org/apache/qpid/transport/Connection.java index e87851cf7d..cdca726148 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/Connection.java +++ b/java/common/src/main/java/org/apache/qpid/transport/Connection.java @@ -21,12 +21,7 @@ package org.apache.qpid.transport; import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.transport.network.Assembler; -import org.apache.qpid.transport.network.Disassembler; -import org.apache.qpid.transport.network.InputHandler; -import org.apache.qpid.transport.network.NetworkConnection; -import org.apache.qpid.transport.network.OutgoingNetworkTransport; -import org.apache.qpid.transport.network.Transport; +import org.apache.qpid.transport.network.*; import org.apache.qpid.transport.network.security.SecurityLayer; import org.apache.qpid.transport.network.security.SecurityLayerFactory; import org.apache.qpid.transport.util.Logger; @@ -73,6 +68,8 @@ public class Connection extends ConnectionInvoker //Usable channels are numbered 0 to - 1 public static final int MAX_CHANNEL_MAX = 0xFFFF; public static final int MIN_USABLE_CHANNEL_NUM = 0; + private long _lastSendTime; + private long _lastReadTime; public enum State { NEW, CLOSED, OPENING, OPEN, CLOSING, CLOSE_RCVD, RESUMING } @@ -89,15 +86,15 @@ public class Connection extends ConnectionInvoker public static interface SessionFactory { - Session newSession(Connection conn, Binary name, long expiry); + Session newSession(Connection conn, Binary name, long expiry, boolean isNoReplay); } private static final class DefaultSessionFactory implements SessionFactory { - public Session newSession(final Connection conn, final Binary name, final long expiry) + public Session newSession(final Connection conn, final Binary name, final long expiry, final boolean isNoReplay) { - return new Session(conn, name, expiry); + return new Session(conn, name, expiry, isNoReplay); } } @@ -232,9 +229,10 @@ public class Connection extends ConnectionInvoker addConnectionListener((ConnectionListener)secureReceiver); } - NetworkConnection network = transport.connect(settings, secureReceiver, null); - _remoteAddress = network.getRemoteAddress(); - _localAddress = network.getLocalAddress(); + NetworkConnection network = transport.connect(settings, secureReceiver, new ConnectionActivity()); + + setRemoteAddress(network.getRemoteAddress()); + setLocalAddress(network.getLocalAddress()); final Sender secureSender = securityLayer.sender(network.getSender()); if(secureSender instanceof ConnectionListener) @@ -298,7 +296,12 @@ public class Connection extends ConnectionInvoker public Session createSession(long expiry) { - return createSession(UUID.randomUUID().toString(), expiry); + return createSession(expiry, false); + } + + public Session createSession(long expiry, boolean isNoReplay) + { + return createSession(UUID.randomUUID().toString(), expiry, isNoReplay); } public Session createSession(String name) @@ -311,12 +314,22 @@ public class Connection extends ConnectionInvoker return createSession(Strings.toUTF8(name), expiry); } + public Session createSession(String name, long expiry,boolean isNoReplay) + { + return createSession(new Binary(Strings.toUTF8(name)), expiry, isNoReplay); + } + public Session createSession(byte[] name, long expiry) { return createSession(new Binary(name), expiry); } public Session createSession(Binary name, long expiry) + { + return createSession(name, expiry, false); + } + + public Session createSession(Binary name, long expiry, boolean isNoReplay) { synchronized (lock) { @@ -331,7 +344,7 @@ public class Connection extends ConnectionInvoker throw new ConnectionException("Timed out waiting for connection to be ready. Current state is :" + state); } - Session ssn = _sessionFactory.newSession(this, name, expiry); + Session ssn = _sessionFactory.newSession(this, name, expiry, isNoReplay); registerSession(ssn); map(ssn); ssn.attach(); @@ -369,6 +382,7 @@ public class Connection extends ConnectionInvoker public void received(ProtocolEvent event) { + _lastReadTime = System.currentTimeMillis(); if(log.isDebugEnabled()) { log.debug("RECV: [%s] %s", this, event); @@ -378,6 +392,7 @@ public class Connection extends ConnectionInvoker public void send(ProtocolEvent event) { + _lastSendTime = System.currentTimeMillis(); if(log.isDebugEnabled()) { log.debug("SEND: [%s] %s", this, event); @@ -728,6 +743,17 @@ public class Connection extends ConnectionInvoker return _localAddress; } + protected void setRemoteAddress(SocketAddress remoteAddress) + { + _remoteAddress = remoteAddress; + } + + protected void setLocalAddress(SocketAddress localAddress) + { + _localAddress = localAddress; + } + + private void invokeSessionDetached(int channel, SessionDetachCode sessionDetachCode) { SessionDetached sessionDetached = new SessionDetached(); @@ -735,4 +761,38 @@ public class Connection extends ConnectionInvoker sessionDetached.setCode(sessionDetachCode); invoke(sessionDetached); } + + + protected void doHeartBeat() + { + connectionHeartbeat(); + } + + private class ConnectionActivity implements TransportActivity + { + @Override + public long getLastReadTime() + { + return _lastReadTime; + } + + @Override + public long getLastWriteTime() + { + return _lastSendTime; + } + + @Override + public void writerIdle() + { + connectionHeartbeat(); + } + + @Override + public void readerIdle() + { + // TODO + + } + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java b/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java index 20d6f98fa6..12f8d801dc 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java +++ b/java/common/src/main/java/org/apache/qpid/transport/NetworkTransportConfiguration.java @@ -38,14 +38,6 @@ public interface NetworkTransportConfiguration // The amount of memory in bytes to allocate to the outgoing buffer Integer getSendBufferSize(); - Integer getPort(); - - String getHost(); - - String getTransport(); - - Integer getConnectorProcessors(); - InetSocketAddress getAddress(); boolean needClientAuth(); diff --git a/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java index e9a7d51456..1e0d5b9698 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java +++ b/java/common/src/main/java/org/apache/qpid/transport/ServerDelegate.java @@ -71,7 +71,8 @@ public class ServerDelegate extends ConnectionDelegate if (mechanism == null || mechanism.length() == 0) { - tuneAuthorizedConnection(conn); + conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, + "No Sasl mechanism was specified"); return; } @@ -82,7 +83,7 @@ public class ServerDelegate extends ConnectionDelegate if (ss == null) { conn.connectionClose(ConnectionCloseCode.CONNECTION_FORCED, - "null SASL mechanism: " + mechanism); + "No SaslServer could be created for mechanism: " + mechanism); return; } conn.setSaslServer(ss); diff --git a/java/common/src/main/java/org/apache/qpid/transport/Session.java b/java/common/src/main/java/org/apache/qpid/transport/Session.java index 95c3e4669f..8b29d6e424 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/Session.java +++ b/java/common/src/main/java/org/apache/qpid/transport/Session.java @@ -25,7 +25,6 @@ import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.transport.network.Frame; import org.apache.qpid.transport.util.Logger; import org.apache.qpid.transport.util.Waiter; - import static org.apache.qpid.transport.Option.COMPLETED; import static org.apache.qpid.transport.Option.SYNC; import static org.apache.qpid.transport.Option.TIMELY_REPLY; @@ -132,19 +131,31 @@ public class Session extends SessionInvoker private final Object stateLock = new Object(); private final AtomicBoolean _failoverRequired = new AtomicBoolean(false); + private boolean _isNoReplay = false; protected Session(Connection connection, Binary name, long expiry) { this(connection, new SessionDelegate(), name, expiry); } + protected Session(Connection connection, Binary name, long expiry, boolean noReplay) + { + this(connection, new SessionDelegate(), name, expiry, noReplay); + } + protected Session(Connection connection, SessionDelegate delegate, Binary name, long expiry) + { + this(connection, delegate, name, expiry,false); + } + + protected Session(Connection connection, SessionDelegate delegate, Binary name, long expiry, boolean noReplay) { this.connection = connection; this.delegate = delegate; this.name = name; this.expiry = expiry; this.closing = false; + this._isNoReplay = noReplay; initReceiver(); } @@ -282,6 +293,7 @@ public class Session extends SessionInvoker void resume() { _failoverRequired.set(false); + synchronized (commandsLock) { attach(); @@ -414,7 +426,7 @@ public class Session extends SessionInvoker if(log.isDebugEnabled()) { - log.debug("ID: [%s] %s", this.channel, id); + log.debug("identify: ch=%s, commandId=%s", this.channel, id); } if ((id & 0xff) == 0) @@ -443,7 +455,7 @@ public class Session extends SessionInvoker { if(log.isDebugEnabled()) { - log.debug("%s processed([%d,%d]) %s %s", this, lower, upper, syncPoint, maxProcessed); + log.debug("%s ch=%s processed([%d,%d]) %s %s", this, channel, lower, upper, syncPoint, maxProcessed); } boolean flush; @@ -451,7 +463,7 @@ public class Session extends SessionInvoker { if(log.isDebugEnabled()) { - log.debug("%s", processed); + log.debug("%s processed: %s", this, processed); } if (ge(upper, commandsIn)) @@ -740,7 +752,7 @@ public class Session extends SessionInvoker sessionCommandPoint(0, 0); } - boolean replayTransfer = !closing && !transacted && + boolean replayTransfer = !_isNoReplay && !closing && !transacted && m instanceof MessageTransfer && ! m.isUnreliable(); diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java index 4d4274278f..8437ef1a94 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/IncomingNetworkTransport.java @@ -27,5 +27,7 @@ import javax.net.ssl.SSLContext; public interface IncomingNetworkTransport extends NetworkTransport { - public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext); + public void accept(NetworkTransportConfiguration config, + ProtocolEngineFactory factory, + SSLContext sslContext); } \ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java index 12c42d6643..050d194c47 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java @@ -50,4 +50,8 @@ public interface NetworkConnection void setPeerPrincipal(Principal principal); Principal getPeerPrincipal(); + + int getMaxReadIdle(); + + int getMaxWriteIdle(); } diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java index 854d76430b..45231aa05d 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/OutgoingNetworkTransport.java @@ -23,12 +23,13 @@ package org.apache.qpid.transport.network; import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.Receiver; -import javax.net.ssl.SSLContext; import java.nio.ByteBuffer; public interface OutgoingNetworkTransport extends NetworkTransport { public NetworkConnection getConnection(); - public NetworkConnection connect(ConnectionSettings settings, Receiver delegate, SSLContext sslContext); + public NetworkConnection connect(ConnectionSettings settings, + Receiver delegate, + TransportActivity transportActivity); } \ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Ticker.java b/java/common/src/main/java/org/apache/qpid/transport/network/Ticker.java new file mode 100644 index 0000000000..210b014a57 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/Ticker.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.transport.network; + +public interface Ticker +{ + int getTimeToNextTick(long currentTime); + + int tick(long currentTime); +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/TransportActivity.java b/java/common/src/main/java/org/apache/qpid/transport/network/TransportActivity.java new file mode 100644 index 0000000000..2ee336d9b2 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/TransportActivity.java @@ -0,0 +1,33 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.transport.network; + +public interface TransportActivity +{ + long getLastReadTime(); + + long getLastWriteTime(); + + void writerIdle(); + + void readerIdle(); +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IdleTimeoutTicker.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IdleTimeoutTicker.java new file mode 100644 index 0000000000..54a2a360bb --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IdleTimeoutTicker.java @@ -0,0 +1,87 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.transport.network.io; + +import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.transport.network.Ticker; +import org.apache.qpid.transport.network.TransportActivity; + +class IdleTimeoutTicker implements Ticker +{ + private final TransportActivity _transport; + private final int _defaultTimeout; + private NetworkConnection _connection; + + public IdleTimeoutTicker(TransportActivity transport, int defaultTimeout) + { + _transport = transport; + _defaultTimeout = defaultTimeout; + } + + @Override + public int getTimeToNextTick(long currentTime) + { + long nextTime = -1; + final long maxReadIdle = 1000l * _connection.getMaxReadIdle(); + + if(maxReadIdle > 0) + { + nextTime = _transport.getLastReadTime() + maxReadIdle; + } + + long maxWriteIdle = 1000l * _connection.getMaxWriteIdle(); + + if(maxWriteIdle > 0) + { + long writeTime = _transport.getLastWriteTime() + maxWriteIdle; + if(nextTime == -1l || writeTime < nextTime) + { + nextTime = writeTime; + } + } + return nextTime == -1 ? _defaultTimeout : (int) (nextTime - currentTime); + } + + @Override + public int tick(long currentTime) + { + // writer Idle + long maxWriteIdle = 1000l * _connection.getMaxWriteIdle(); + if(maxWriteIdle > 0 && maxWriteIdle+ _transport.getLastWriteTime() <= currentTime) + { + _transport.writerIdle(); + } + // reader Idle + final long maxReadIdle = 1000l * _connection.getMaxReadIdle(); + if(maxReadIdle > 0 && maxReadIdle+ _transport.getLastReadTime() <= currentTime) + { + + _transport.readerIdle(); + } + return getTimeToNextTick(currentTime); + } + + public void setConnection(NetworkConnection connection) + { + _connection = connection; + } +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java index 2658296c5f..f5c09ac2cc 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java @@ -26,7 +26,9 @@ import java.nio.ByteBuffer; import java.security.Principal; import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.network.Ticker; import org.apache.qpid.transport.network.NetworkConnection; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,14 +40,23 @@ public class IoNetworkConnection implements NetworkConnection private final IoSender _ioSender; private final IoReceiver _ioReceiver; private Principal _principal; + private int _maxReadIdle; + private int _maxWriteIdle; public IoNetworkConnection(Socket socket, Receiver delegate, - int sendBufferSize, int receiveBufferSize, long timeout) + int sendBufferSize, int receiveBufferSize, long timeout) + { + this(socket,delegate,sendBufferSize,receiveBufferSize,timeout,null); + } + + public IoNetworkConnection(Socket socket, Receiver delegate, + int sendBufferSize, int receiveBufferSize, long timeout, Ticker ticker) { _socket = socket; _timeout = timeout; _ioReceiver = new IoReceiver(_socket, delegate, receiveBufferSize,_timeout); + _ioReceiver.setTicker(ticker); _ioSender = new IoSender(_socket, 2 * sendBufferSize, _timeout); @@ -88,14 +99,12 @@ public class IoNetworkConnection implements NetworkConnection public void setMaxWriteIdle(int sec) { - // TODO implement support for setting heartbeating config in this way - // Currently a socket timeout is used in IoSender + _maxWriteIdle = sec; } public void setMaxReadIdle(int sec) { - // TODO implement support for setting heartbeating config in this way - // Currently a socket timeout is used in IoSender + _maxReadIdle = sec; } @Override @@ -109,4 +118,16 @@ public class IoNetworkConnection implements NetworkConnection { return _principal; } + + @Override + public int getMaxReadIdle() + { + return _maxReadIdle; + } + + @Override + public int getMaxWriteIdle() + { + return _maxWriteIdle; + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java index 9b6f0a0b1b..c8027e143e 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java @@ -41,9 +41,8 @@ import org.apache.qpid.transport.ConnectionSettings; import org.apache.qpid.transport.NetworkTransportConfiguration; import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.TransportException; -import org.apache.qpid.transport.network.IncomingNetworkTransport; -import org.apache.qpid.transport.network.NetworkConnection; -import org.apache.qpid.transport.network.OutgoingNetworkTransport; +import org.apache.qpid.transport.network.*; + import org.slf4j.LoggerFactory; public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNetworkTransport @@ -56,7 +55,9 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet private IoNetworkConnection _connection; private AcceptingThread _acceptor; - public NetworkConnection connect(ConnectionSettings settings, Receiver delegate, SSLContext sslContext) + public NetworkConnection connect(ConnectionSettings settings, + Receiver delegate, + TransportActivity transportActivity) { int sendBufferSize = settings.getWriteBufferSize(); int receiveBufferSize = settings.getReadBufferSize(); @@ -91,7 +92,9 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet try { - _connection = new IoNetworkConnection(_socket, delegate, sendBufferSize, receiveBufferSize, TIMEOUT); + IdleTimeoutTicker ticker = new IdleTimeoutTicker(transportActivity, TIMEOUT); + _connection = new IoNetworkConnection(_socket, delegate, sendBufferSize, receiveBufferSize, TIMEOUT, ticker); + ticker.setConnection(_connection); _connection.start(); } catch(Exception e) @@ -128,9 +131,10 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet return _connection; } - public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext) + public void accept(NetworkTransportConfiguration config, + ProtocolEngineFactory factory, + SSLContext sslContext) { - try { _acceptor = new AcceptingThread(config, factory, sslContext); @@ -141,8 +145,6 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet { throw new TransportException("Unable to start server socket", e); } - - } private class AcceptingThread extends Thread @@ -152,15 +154,16 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet private ProtocolEngineFactory _factory; private SSLContext _sslContext; private ServerSocket _serverSocket; + private int _timeout; private AcceptingThread(NetworkTransportConfiguration config, ProtocolEngineFactory factory, - SSLContext sslContext) - throws IOException + SSLContext sslContext) throws IOException { _config = config; _factory = factory; _sslContext = sslContext; + _timeout = TIMEOUT; InetSocketAddress address = config.getAddress(); @@ -172,15 +175,19 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet { SSLServerSocketFactory socketFactory = _sslContext.getServerSocketFactory(); _serverSocket = socketFactory.createServerSocket(); - ((SSLServerSocket)_serverSocket).setNeedClientAuth(config.needClientAuth()); - ((SSLServerSocket)_serverSocket).setWantClientAuth(config.wantClientAuth()); + if(config.needClientAuth()) + { + ((SSLServerSocket)_serverSocket).setNeedClientAuth(true); + } + else if(config.wantClientAuth()) + { + ((SSLServerSocket)_serverSocket).setWantClientAuth(true); + } } _serverSocket.setReuseAddress(true); _serverSocket.bind(address); - - } @@ -217,6 +224,7 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet { socket = _serverSocket.accept(); socket.setTcpNoDelay(_config.getTcpNoDelay()); + socket.setSoTimeout(_timeout); final Integer sendBufferSize = _config.getSendBufferSize(); final Integer receiveBufferSize = _config.getReceiveBufferSize(); @@ -224,10 +232,12 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet socket.setSendBufferSize(sendBufferSize); socket.setReceiveBufferSize(receiveBufferSize); - ProtocolEngine engine = _factory.newProtocolEngine(); - NetworkConnection connection = new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, TIMEOUT); + final IdleTimeoutTicker ticker = new IdleTimeoutTicker(engine, TIMEOUT); + NetworkConnection connection = new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, _timeout, + ticker); + ticker.setConnection(connection); if(_sslContext != null) { @@ -248,14 +258,14 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet } catch(RuntimeException e) { - LOGGER.error("Error in Acceptor thread on port " + _config.getPort(), e); + LOGGER.error("Error in Acceptor thread on address " + _config.getAddress(), e); closeSocketIfNecessary(socket); } catch(IOException e) { if(!_closed) { - LOGGER.error("Error in Acceptor thread on port " + _config.getPort(), e); + LOGGER.error("Error in Acceptor thread on address " + _config.getAddress(), e); closeSocketIfNecessary(socket); try { @@ -275,7 +285,7 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet { if(LOGGER.isDebugEnabled()) { - LOGGER.debug("Acceptor exiting, no new connections will be accepted on port " + _config.getPort()); + LOGGER.debug("Acceptor exiting, no new connections will be accepted on address " + _config.getAddress()); } } } @@ -294,6 +304,7 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet } } } + } } diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java index 7e63071c16..06a43e21c6 100644 --- a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java @@ -24,6 +24,7 @@ import org.apache.qpid.common.Closeable; import org.apache.qpid.thread.Threading; import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.TransportException; +import org.apache.qpid.transport.network.Ticker; import org.apache.qpid.transport.util.Logger; import javax.net.ssl.SSLSocket; @@ -31,6 +32,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.Socket; import java.net.SocketException; +import java.net.SocketTimeoutException; import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicBoolean; @@ -51,6 +53,8 @@ final class IoReceiver implements Runnable, Closeable private final AtomicBoolean closed = new AtomicBoolean(false); private final Thread receiverThread; private static final boolean shutdownBroken; + + private Ticker _ticker; static { String osName = System.getProperty("os.name"); @@ -136,7 +140,7 @@ final class IoReceiver implements Runnable, Closeable { final int threshold = bufferSize / 2; - // I set the read buffer size simillar to SO_RCVBUF + // I set the read buffer size similar to SO_RCVBUF // Haven't tested with a lower value to see if it's better or worse byte[] buffer = new byte[bufferSize]; try @@ -144,27 +148,71 @@ final class IoReceiver implements Runnable, Closeable InputStream in = socket.getInputStream(); int read = 0; int offset = 0; - while ((read = in.read(buffer, offset, bufferSize-offset)) != -1) + long currentTime; + while(read != -1) { - if (read > 0) + try + { + while ((read = in.read(buffer, offset, bufferSize-offset)) != -1) + { + if (read > 0) + { + ByteBuffer b = ByteBuffer.wrap(buffer,offset,read); + receiver.received(b); + offset+=read; + if (offset > threshold) + { + offset = 0; + buffer = new byte[bufferSize]; + } + } + currentTime = System.currentTimeMillis(); + + if(_ticker != null) + { + int tick = _ticker.getTimeToNextTick(currentTime); + if(tick <= 0) + { + tick = _ticker.tick(currentTime); + } + try + { + if(!socket.isClosed()) + { + socket.setSoTimeout(tick <= 0 ? 1 : tick); + } + } + catch(SocketException e) + { + // ignore - closed socket + } + } + } + } + catch (SocketTimeoutException e) { - ByteBuffer b = ByteBuffer.wrap(buffer,offset,read); - receiver.received(b); - offset+=read; - if (offset > threshold) + currentTime = System.currentTimeMillis(); + if(_ticker != null) { - offset = 0; - buffer = new byte[bufferSize]; + final int tick = _ticker.tick(currentTime); + if(!socket.isClosed()) + { + try + { + socket.setSoTimeout(tick <= 0 ? 1 : tick ); + } + catch(SocketException ex) + { + // ignore - closed socket + } + } } } } } catch (Throwable t) { - if (!(shutdownBroken && - t instanceof SocketException && - t.getMessage().equalsIgnoreCase("socket closed") && - closed.get())) + if (shouldReport(t)) { receiver.exception(t); } @@ -183,4 +231,30 @@ final class IoReceiver implements Runnable, Closeable } } + private boolean shouldReport(Throwable t) + { + boolean brokenClose = closed.get() && + shutdownBroken && + t instanceof SocketException && + "socket closed".equalsIgnoreCase(t.getMessage()); + + boolean sslSocketClosed = closed.get() && + socket instanceof SSLSocket && + t instanceof SocketException && + "Socket is closed".equalsIgnoreCase(t.getMessage()); + + return !brokenClose && !sslSocketClosed; + } + + public Ticker getTicker() + { + return _ticker; + } + + public void setTicker(Ticker ticker) + { + _ticker = ticker; + } + + } diff --git a/java/common/src/main/java/org/apache/qpid/url/BindingURL.java b/java/common/src/main/java/org/apache/qpid/url/BindingURL.java index 0e6c865a16..61585443b1 100644 --- a/java/common/src/main/java/org/apache/qpid/url/BindingURL.java +++ b/java/common/src/main/java/org/apache/qpid/url/BindingURL.java @@ -36,6 +36,9 @@ public interface BindingURL public static final String OPTION_SUBSCRIPTION = "subscription"; public static final String OPTION_ROUTING_KEY = "routingkey"; public static final String OPTION_BINDING_KEY = "bindingkey"; + public static final String OPTION_EXCHANGE_AUTODELETE = "exchangeautodelete"; + public static final String OPTION_EXCHANGE_DURABLE = "exchangedurable"; + public static final String OPTION_EXCHANGE_INTERNAL = "exchangeinternal"; /** * This option is only applicable for 0-8/0-9/0-9-1 protocols connection diff --git a/java/common/src/main/java/org/apache/qpid/util/FileUtils.java b/java/common/src/main/java/org/apache/qpid/util/FileUtils.java index 2d3e321812..7362099070 100644 --- a/java/common/src/main/java/org/apache/qpid/util/FileUtils.java +++ b/java/common/src/main/java/org/apache/qpid/util/FileUtils.java @@ -220,6 +220,19 @@ public class FileUtils public static void copyCheckedEx(File src, File dst) throws IOException { InputStream in = new FileInputStream(src); + copy(in, dst); + } + + /** + * Copies the specified InputStream to the specified destination file. If the destination file does not exist, + * it is created. + * + * @param in The InputStream + * @param dst The destination file name. + * @throws IOException + */ + public static void copy(InputStream in, File dst) throws IOException + { try { if (!dst.exists()) diff --git a/java/common/src/main/java/org/apache/qpid/util/NetMatcher.java b/java/common/src/main/java/org/apache/qpid/util/NetMatcher.java deleted file mode 100644 index 971dd3fe2a..0000000000 --- a/java/common/src/main/java/org/apache/qpid/util/NetMatcher.java +++ /dev/null @@ -1,300 +0,0 @@ -/*********************************************************************** - * Copyright (c) 2000-2006 The Apache Software Foundation. * - * All rights reserved. * - * ------------------------------------------------------------------- * - * 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.util; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; - -public class NetMatcher -{ - private ArrayList networks; - - public void initInetNetworks(final Collection nets) - { - networks = new ArrayList(); - for (Iterator iter = nets.iterator(); iter.hasNext(); ) - { - try - { - InetNetwork net = InetNetwork.getFromString((String) iter.next()); - if (!networks.contains(net)) - { - networks.add(net); - } - } - catch (java.net.UnknownHostException uhe) - { - log("Cannot resolve address: " + uhe.getMessage()); - } - } - networks.trimToSize(); - } - - public void initInetNetworks(final String[] nets) - { - networks = new ArrayList(); - for (int i = 0; i < nets.length; i++) - { - try - { - InetNetwork net = InetNetwork.getFromString(nets[i]); - if (!networks.contains(net)) - { - networks.add(net); - } - } - catch (java.net.UnknownHostException uhe) - { - log("Cannot resolve address: " + uhe.getMessage()); - } - } - networks.trimToSize(); - } - - public boolean matchInetNetwork(final String hostIP) - { - InetAddress ip = null; - - try - { - ip = InetAddress.getByName(hostIP); - } - catch (java.net.UnknownHostException uhe) - { - log("Cannot resolve address for " + hostIP + ": " + uhe.getMessage()); - } - - boolean sameNet = false; - - if (ip != null) - { - for (Iterator iter = networks.iterator(); (!sameNet) && iter.hasNext(); ) - { - InetNetwork network = (InetNetwork) iter.next(); - sameNet = network.contains(ip); - } - } - return sameNet; - } - - public boolean matchInetNetwork(final InetAddress ip) - { - boolean sameNet = false; - - for (Iterator iter = networks.iterator(); (!sameNet) && iter.hasNext(); ) - { - InetNetwork network = (InetNetwork) iter.next(); - sameNet = network.contains(ip); - } - return sameNet; - } - - public NetMatcher() - { - } - - public NetMatcher(final String[] nets) - { - initInetNetworks(nets); - } - - public NetMatcher(final Collection nets) - { - initInetNetworks(nets); - } - - public String toString() { - return networks.toString(); - } - - protected void log(String s) { } -} - -class InetNetwork -{ - /* - * Implements network masking, and is compatible with RFC 1518 and - * RFC 1519, which describe CIDR: Classless Inter-Domain Routing. - */ - - private InetAddress network; - private InetAddress netmask; - - public InetNetwork(InetAddress ip, InetAddress netmask) - { - network = maskIP(ip, netmask); - this.netmask = netmask; - } - - public boolean contains(final String name) throws java.net.UnknownHostException - { - return network.equals(maskIP(InetAddress.getByName(name), netmask)); - } - - public boolean contains(final InetAddress ip) - { - return network.equals(maskIP(ip, netmask)); - } - - public String toString() - { - return network.getHostAddress() + "/" + netmask.getHostAddress(); - } - - public int hashCode() - { - return maskIP(network, netmask).hashCode(); - } - - public boolean equals(Object obj) - { - return (obj != null) && (obj instanceof InetNetwork) && - ((((InetNetwork)obj).network.equals(network)) && (((InetNetwork)obj).netmask.equals(netmask))); - } - - public static InetNetwork getFromString(String netspec) throws java.net.UnknownHostException - { - if (netspec.endsWith("*")) - { - netspec = normalizeFromAsterisk(netspec); - } - else - { - int iSlash = netspec.indexOf('/'); - if (iSlash == -1) - { - netspec += "/255.255.255.255"; - } - else if (netspec.indexOf('.', iSlash) == -1) - { - netspec = normalizeFromCIDR(netspec); - } - } - - return new InetNetwork(InetAddress.getByName(netspec.substring(0, netspec.indexOf('/'))), - InetAddress.getByName(netspec.substring(netspec.indexOf('/') + 1))); - } - - public static InetAddress maskIP(final byte[] ip, final byte[] mask) - { - try - { - return getByAddress(new byte[] - { - (byte) (mask[0] & ip[0]), - (byte) (mask[1] & ip[1]), - (byte) (mask[2] & ip[2]), - (byte) (mask[3] & ip[3]) - }); - } - catch(Exception _) {} - { - return null; - } - } - - public static InetAddress maskIP(final InetAddress ip, final InetAddress mask) - { - return maskIP(ip.getAddress(), mask.getAddress()); - } - - /* - * This converts from an uncommon "wildcard" CIDR format - * to "address + mask" format: - * - * * => 000.000.000.0/000.000.000.0 - * xxx.* => xxx.000.000.0/255.000.000.0 - * xxx.xxx.* => xxx.xxx.000.0/255.255.000.0 - * xxx.xxx.xxx.* => xxx.xxx.xxx.0/255.255.255.0 - */ - static private String normalizeFromAsterisk(final String netspec) - { - String[] masks = { "0.0.0.0/0.0.0.0", "0.0.0/255.0.0.0", "0.0/255.255.0.0", "0/255.255.255.0" }; - char[] srcb = netspec.toCharArray(); - int octets = 0; - for (int i = 1; i < netspec.length(); i++) - { - if (srcb[i] == '.') - { - octets++; - } - } - return (octets == 0) ? masks[0] : netspec.substring(0, netspec.length() -1 ).concat(masks[octets]); - } - - /* - * RFC 1518, 1519 - Classless Inter-Domain Routing (CIDR) - * This converts from "prefix + prefix-length" format to - * "address + mask" format, e.g. from xxx.xxx.xxx.xxx/yy - * to xxx.xxx.xxx.xxx/yyy.yyy.yyy.yyy. - */ - static private String normalizeFromCIDR(final String netspec) - { - final int bits = 32 - Integer.parseInt(netspec.substring(netspec.indexOf('/')+1)); - final int mask = (bits == 32) ? 0 : 0xFFFFFFFF - ((1 << bits)-1); - - return netspec.substring(0, netspec.indexOf('/') + 1) + - Integer.toString(mask >> 24 & 0xFF, 10) + "." + - Integer.toString(mask >> 16 & 0xFF, 10) + "." + - Integer.toString(mask >> 8 & 0xFF, 10) + "." + - Integer.toString(mask >> 0 & 0xFF, 10); - } - - private static java.lang.reflect.Method getByAddress = null; - - static { - try { - Class inetAddressClass = Class.forName("java.net.InetAddress"); - Class[] parameterTypes = { byte[].class }; - getByAddress = inetAddressClass.getMethod("getByAddress", parameterTypes); - } catch (Exception e) { - getByAddress = null; - } - } - - private static InetAddress getByAddress(byte[] ip) throws java.net.UnknownHostException - { - InetAddress addr = null; - if (getByAddress != null) - { - try - { - addr = (InetAddress) getByAddress.invoke(null, new Object[] { ip }); - } - catch (IllegalAccessException e) - { - } - catch (java.lang.reflect.InvocationTargetException e) - { - } - } - - if (addr == null) { - addr = InetAddress.getByName - ( - Integer.toString(ip[0] & 0xFF, 10) + "." + - Integer.toString(ip[1] & 0xFF, 10) + "." + - Integer.toString(ip[2] & 0xFF, 10) + "." + - Integer.toString(ip[3] & 0xFF, 10) - ); - } - return addr; - } -} diff --git a/java/common/src/test/java/org/apache/qpid/framing/FieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/FieldTableTest.java new file mode 100644 index 0000000000..1ecf450551 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/framing/FieldTableTest.java @@ -0,0 +1,938 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.framing; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.qpid.AMQPInvalidClassException; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class FieldTableTest extends TestCase +{ + /** + * Test that setting a similar named value replaces any previous value set on that name + */ + public void testReplacement() + { + FieldTable table1 = new FieldTable(); + // Set a boolean value + table1.setBoolean("value", true); + // Check length of table is correct ( + + ) + int size = EncodingUtils.encodedShortStringLength("value") + 1 + EncodingUtils.encodedBooleanLength(); + Assert.assertEquals(size, table1.getEncodedSize()); + + // reset value to an integer + table1.setInteger("value", Integer.MAX_VALUE); + + // Check the length has changed accordingly ( + + ) + size = EncodingUtils.encodedShortStringLength("value") + 1 + EncodingUtils.encodedIntegerLength(); + Assert.assertEquals(size, table1.getEncodedSize()); + + // Check boolean value is null + Assert.assertEquals(null, table1.getBoolean("value")); + // ... and integer value is good + Assert.assertEquals((Integer) Integer.MAX_VALUE, table1.getInteger("value")); + } + + /** + * Set a boolean and check that we can only get it back as a boolean and a string + * Check that attempting to lookup a non existent value returns null + */ + public void testBoolean() + { + FieldTable table1 = new FieldTable(); + table1.setBoolean("value", true); + Assert.assertTrue(table1.propertyExists("value")); + + // Test Getting right value back + Assert.assertEquals((Boolean) true, table1.getBoolean("value")); + + // Check we don't get anything back for other gets + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + // except value as a string + Assert.assertEquals("true", table1.getString("value")); + + table1.remove("value"); + + // Table should now have zero length for encoding + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getBoolean("Rubbish")); + } + + /** + * Set a byte and check that we can only get it back as a byte and a string + * Check that attempting to lookup a non existent value returns null + */ + public void testByte() + { + FieldTable table1 = new FieldTable(); + table1.setByte("value", Byte.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + // Tests lookups we shouldn't get anything back for other gets + // we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + // ... and a the string value of it. + Assert.assertEquals("" + Byte.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + // Table should now have zero length for encoding + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getByte("Rubbish")); + } + + /** + * Set a short and check that we can only get it back as a short and a string + * Check that attempting to lookup a non existent value returns null + */ + public void testShort() + { + FieldTable table1 = new FieldTable(); + table1.setShort("value", Short.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + // Tests lookups we shouldn't get anything back for other gets + // we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(Short.MAX_VALUE, (short) table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + // ... and a the string value of it. + Assert.assertEquals("" + Short.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + // Table should now have zero length for encoding + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getShort("Rubbish")); + } + + /** + * Set a char and check that we can only get it back as a char + * Check that attempting to lookup a non existent value returns null + */ + public void testChar() + { + FieldTable table1 = new FieldTable(); + table1.setChar("value", 'c'); + Assert.assertTrue(table1.propertyExists("value")); + + // Tests lookups we shouldn't get anything back for other gets + // we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals('c', (char) table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + // ... and a the string value of it. + Assert.assertEquals("c", table1.getString("value")); + + table1.remove("value"); + + // Table should now have zero length for encoding + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getCharacter("Rubbish")); + } + + /** + * Set a double and check that we can only get it back as a double + * Check that attempting to lookup a non existent value returns null + */ + public void testDouble() + { + FieldTable table1 = new FieldTable(); + table1.setDouble("value", Double.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + // Tests lookups we shouldn't get anything back for other gets + // we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(Double.MAX_VALUE, (double) table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + // ... and a the string value of it. + Assert.assertEquals("" + Double.MAX_VALUE, table1.getString("value")); + table1.remove("value"); + // but after a removeKey it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero length for encoding + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getDouble("Rubbish")); + } + + /** + * Set a float and check that we can only get it back as a float + * Check that attempting to lookup a non existent value returns null + */ + public void testFloat() + { + FieldTable table1 = new FieldTable(); + table1.setFloat("value", Float.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + // Tests lookups we shouldn't get anything back for other gets + // we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(Float.MAX_VALUE, (float) table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + // ... and a the string value of it. + Assert.assertEquals("" + Float.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + // but after a removeKey it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero length for encoding + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getFloat("Rubbish")); + } + + /** + * Set an int and check that we can only get it back as an int + * Check that attempting to lookup a non existent value returns null + */ + public void testInt() + { + FieldTable table1 = new FieldTable(); + table1.setInteger("value", Integer.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + // Tets lookups we shouldn't get anything back for other gets + // we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(Integer.MAX_VALUE, (int) table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + // ... and a the string value of it. + Assert.assertEquals("" + Integer.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + // but after a removeKey it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero length for encoding + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getInteger("Rubbish")); + } + + /** + * Set a long and check that we can only get it back as a long + * Check that attempting to lookup a non existent value returns null + */ + public void testLong() + { + FieldTable table1 = new FieldTable(); + table1.setLong("value", Long.MAX_VALUE); + Assert.assertTrue(table1.propertyExists("value")); + + // Tets lookups we shouldn't get anything back for other gets + // we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(Long.MAX_VALUE, (long) table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + + // ... and a the string value of it. + Assert.assertEquals("" + Long.MAX_VALUE, table1.getString("value")); + + table1.remove("value"); + // but after a removeKey it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero length for encoding + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getLong("Rubbish")); + } + + /** + * Set a double and check that we can only get it back as a double + * Check that attempting to lookup a non existent value returns null + */ + public void testBytes() + { + byte[] bytes = { 99, 98, 97, 96, 95 }; + + FieldTable table1 = new FieldTable(); + table1.setBytes("value", bytes); + Assert.assertTrue(table1.propertyExists("value")); + + // Tets lookups we shouldn't get anything back for other gets + // we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + assertBytesEqual(bytes, table1.getBytes("value")); + + // ... and a the string value of it is null + Assert.assertEquals(null, table1.getString("value")); + + table1.remove("value"); + // but after a removeKey it doesn't + Assert.assertFalse(table1.containsKey("value")); + + // Table should now have zero length for encoding + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getBytes("Rubbish")); + } + + /** + * Calls all methods that can be used to check the table is empty + * - getEncodedSize + * - isEmpty + * - length + * + * @param table to check is empty + */ + private void checkEmpty(FieldTable table) + { + Assert.assertEquals(0, table.getEncodedSize()); + Assert.assertTrue(table.isEmpty()); + Assert.assertEquals(0, table.size()); + + Assert.assertEquals(0, table.keySet().size()); + } + + /** + * Set a String and check that we can only get it back as a String + * Check that attempting to lookup a non existent value returns null + */ + public void testString() + { + FieldTable table1 = new FieldTable(); + table1.setString("value", "Hello"); + Assert.assertTrue(table1.propertyExists("value")); + + // Test lookups we shouldn't get anything back for other gets + // we should get right value back for this type .... + Assert.assertEquals(null, table1.getBoolean("value")); + Assert.assertEquals(null, table1.getByte("value")); + Assert.assertEquals(null, table1.getShort("value")); + Assert.assertEquals(null, table1.getCharacter("value")); + Assert.assertEquals(null, table1.getDouble("value")); + Assert.assertEquals(null, table1.getFloat("value")); + Assert.assertEquals(null, table1.getInteger("value")); + Assert.assertEquals(null, table1.getLong("value")); + Assert.assertEquals(null, table1.getBytes("value")); + Assert.assertEquals("Hello", table1.getString("value")); + + // Try setting a null value and read it back + table1.setString("value", null); + + Assert.assertEquals(null, table1.getString("value")); + + // but still contains the value + Assert.assertTrue(table1.containsKey("value")); + + table1.remove("value"); + // but after a removeKey it doesn't + Assert.assertFalse(table1.containsKey("value")); + + checkEmpty(table1); + + // Looking up an invalid value returns null + Assert.assertEquals(null, table1.getString("Rubbish")); + + // Additional Test that haven't been covered for string + table1.setObject("value", "Hello"); + // Check that it was set correctly + Assert.assertEquals("Hello", table1.getString("value")); + } + + /** Check that a nested field table parameter correctly encodes and decodes to a byte buffer. */ + public void testNestedFieldTable() throws IOException + { + byte[] testBytes = new byte[] { 0, 1, 2, 3, 4, 5 }; + + FieldTable outerTable = new FieldTable(); + FieldTable innerTable = new FieldTable(); + + // Put some stuff in the inner table. + innerTable.setBoolean("bool", true); + innerTable.setByte("byte", Byte.MAX_VALUE); + innerTable.setBytes("bytes", testBytes); + innerTable.setChar("char", 'c'); + innerTable.setDouble("double", Double.MAX_VALUE); + innerTable.setFloat("float", Float.MAX_VALUE); + innerTable.setInteger("int", Integer.MAX_VALUE); + innerTable.setLong("long", Long.MAX_VALUE); + innerTable.setShort("short", Short.MAX_VALUE); + innerTable.setString("string", "hello"); + innerTable.setString("null-string", null); + + // Put the inner table in the outer one. + outerTable.setFieldTable("innerTable", innerTable); + + // Write the outer table into the buffer. + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + outerTable.writeToBuffer(new DataOutputStream(baos)); + + byte[] data = baos.toByteArray(); + + // Extract the table back from the buffer again. + try + { + FieldTable extractedOuterTable = EncodingUtils.readFieldTable(new DataInputStream(new ByteArrayInputStream(data))); + + FieldTable extractedTable = extractedOuterTable.getFieldTable("innerTable"); + + Assert.assertEquals((Boolean) true, extractedTable.getBoolean("bool")); + Assert.assertEquals((Byte) Byte.MAX_VALUE, extractedTable.getByte("byte")); + assertBytesEqual(testBytes, extractedTable.getBytes("bytes")); + Assert.assertEquals((Character) 'c', extractedTable.getCharacter("char")); + Assert.assertEquals(Double.MAX_VALUE, extractedTable.getDouble("double")); + Assert.assertEquals(Float.MAX_VALUE, extractedTable.getFloat("float")); + Assert.assertEquals((Integer) Integer.MAX_VALUE, extractedTable.getInteger("int")); + Assert.assertEquals((Long) Long.MAX_VALUE, extractedTable.getLong("long")); + Assert.assertEquals((Short) Short.MAX_VALUE, extractedTable.getShort("short")); + Assert.assertEquals("hello", extractedTable.getString("string")); + Assert.assertEquals(null, extractedTable.getString("null-string")); + } + catch (AMQFrameDecodingException e) + { + fail("Failed to decode field table with nested inner table."); + } + } + + public void testValues() + { + FieldTable table = new FieldTable(); + table.setBoolean("bool", true); + table.setByte("byte", Byte.MAX_VALUE); + byte[] bytes = { 99, 98, 97, 96, 95 }; + table.setBytes("bytes", bytes); + table.setChar("char", 'c'); + table.setDouble("double", Double.MAX_VALUE); + table.setFloat("float", Float.MAX_VALUE); + table.setInteger("int", Integer.MAX_VALUE); + table.setLong("long", Long.MAX_VALUE); + table.setShort("short", Short.MAX_VALUE); + table.setString("string", "Hello"); + table.setString("null-string", null); + + table.setObject("object-bool", true); + table.setObject("object-byte", Byte.MAX_VALUE); + table.setObject("object-bytes", bytes); + table.setObject("object-char", 'c'); + table.setObject("object-double", Double.MAX_VALUE); + table.setObject("object-float", Float.MAX_VALUE); + table.setObject("object-int", Integer.MAX_VALUE); + table.setObject("object-long", Long.MAX_VALUE); + table.setObject("object-short", Short.MAX_VALUE); + table.setObject("object-string", "Hello"); + + try + { + table.setObject("Null-object", null); + fail("null values are not allowed"); + } + catch (AMQPInvalidClassException aice) + { + assertEquals("Null values are not allowed to be set", + AMQPInvalidClassException.INVALID_OBJECT_MSG + "null", aice.getMessage()); + } + + try + { + table.setObject("Unsupported-object", new Exception()); + fail("Non primitive values are not allowed"); + } + catch (AMQPInvalidClassException aice) + { + assertEquals("Non primitive values are not allowed to be set", + AMQPInvalidClassException.INVALID_OBJECT_MSG + Exception.class, aice.getMessage()); + } + + Assert.assertEquals((Boolean) true, table.getBoolean("bool")); + Assert.assertEquals((Byte) Byte.MAX_VALUE, table.getByte("byte")); + assertBytesEqual(bytes, table.getBytes("bytes")); + Assert.assertEquals((Character) 'c', table.getCharacter("char")); + Assert.assertEquals(Double.MAX_VALUE, table.getDouble("double")); + Assert.assertEquals(Float.MAX_VALUE, table.getFloat("float")); + Assert.assertEquals((Integer) Integer.MAX_VALUE, table.getInteger("int")); + Assert.assertEquals((Long) Long.MAX_VALUE, table.getLong("long")); + Assert.assertEquals((Short) Short.MAX_VALUE, table.getShort("short")); + Assert.assertEquals("Hello", table.getString("string")); + Assert.assertEquals(null, table.getString("null-string")); + + Assert.assertEquals(true, table.getObject("object-bool")); + Assert.assertEquals(Byte.MAX_VALUE, table.getObject("object-byte")); + assertBytesEqual(bytes, (byte[]) table.getObject("object-bytes")); + Assert.assertEquals('c', table.getObject("object-char")); + Assert.assertEquals(Double.MAX_VALUE, table.getObject("object-double")); + Assert.assertEquals(Float.MAX_VALUE, table.getObject("object-float")); + Assert.assertEquals(Integer.MAX_VALUE, table.getObject("object-int")); + Assert.assertEquals(Long.MAX_VALUE, table.getObject("object-long")); + Assert.assertEquals(Short.MAX_VALUE, table.getObject("object-short")); + Assert.assertEquals("Hello", table.getObject("object-string")); + } + + public void testWriteBuffer() throws IOException + { + byte[] bytes = { 99, 98, 97, 96, 95 }; + + FieldTable table = new FieldTable(); + table.setBoolean("bool", true); + table.setByte("byte", Byte.MAX_VALUE); + + table.setBytes("bytes", bytes); + table.setChar("char", 'c'); + table.setInteger("int", Integer.MAX_VALUE); + table.setLong("long", Long.MAX_VALUE); + table.setDouble("double", Double.MAX_VALUE); + table.setFloat("float", Float.MAX_VALUE); + table.setShort("short", Short.MAX_VALUE); + table.setString("string", "hello"); + table.setString("null-string", null); + + + ByteArrayOutputStream baos = new ByteArrayOutputStream((int) table.getEncodedSize() + 4); + table.writeToBuffer(new DataOutputStream(baos)); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + DataInputStream dis = new DataInputStream(bais); + + + long length = dis.readInt() & 0xFFFFFFFFL; + + FieldTable table2 = new FieldTable(dis, length); + + Assert.assertEquals((Boolean) true, table2.getBoolean("bool")); + Assert.assertEquals((Byte) Byte.MAX_VALUE, table2.getByte("byte")); + assertBytesEqual(bytes, table2.getBytes("bytes")); + Assert.assertEquals((Character) 'c', table2.getCharacter("char")); + Assert.assertEquals(Double.MAX_VALUE, table2.getDouble("double")); + Assert.assertEquals(Float.MAX_VALUE, table2.getFloat("float")); + Assert.assertEquals((Integer) Integer.MAX_VALUE, table2.getInteger("int")); + Assert.assertEquals((Long) Long.MAX_VALUE, table2.getLong("long")); + Assert.assertEquals((Short) Short.MAX_VALUE, table2.getShort("short")); + Assert.assertEquals("hello", table2.getString("string")); + Assert.assertEquals(null, table2.getString("null-string")); + } + + public void testEncodingSize() + { + FieldTable result = new FieldTable(); + int size = 0; + + result.setBoolean("boolean", true); + size += 1 + EncodingUtils.encodedShortStringLength("boolean") + EncodingUtils.encodedBooleanLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setByte("byte", (byte) Byte.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("byte") + EncodingUtils.encodedByteLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + byte[] _bytes = { 99, 98, 97, 96, 95 }; + + result.setBytes("bytes", _bytes); + size += 1 + EncodingUtils.encodedShortStringLength("bytes") + 4 + _bytes.length; + Assert.assertEquals(size, result.getEncodedSize()); + + result.setChar("char", (char) 'c'); + size += 1 + EncodingUtils.encodedShortStringLength("char") + EncodingUtils.encodedCharLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setDouble("double", (double) Double.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("double") + EncodingUtils.encodedDoubleLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setFloat("float", (float) Float.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("float") + EncodingUtils.encodedFloatLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setInteger("int", (int) Integer.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("int") + EncodingUtils.encodedIntegerLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setLong("long", (long) Long.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("long") + EncodingUtils.encodedLongLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setShort("short", (short) Short.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("short") + EncodingUtils.encodedShortLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setString("result", "Hello"); + size += 1 + EncodingUtils.encodedShortStringLength("result") + EncodingUtils.encodedLongStringLength("Hello"); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setObject("object-bool", true); + size += 1 + EncodingUtils.encodedShortStringLength("object-bool") + EncodingUtils.encodedBooleanLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setObject("object-byte", Byte.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("object-byte") + EncodingUtils.encodedByteLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setObject("object-bytes", _bytes); + size += 1 + EncodingUtils.encodedShortStringLength("object-bytes") + 4 + _bytes.length; + Assert.assertEquals(size, result.getEncodedSize()); + + result.setObject("object-char", 'c'); + size += 1 + EncodingUtils.encodedShortStringLength("object-char") + EncodingUtils.encodedCharLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setObject("object-double", Double.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("object-double") + EncodingUtils.encodedDoubleLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setObject("object-float", Float.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("object-float") + EncodingUtils.encodedFloatLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setObject("object-int", Integer.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("object-int") + EncodingUtils.encodedIntegerLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setObject("object-long", Long.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("object-long") + EncodingUtils.encodedLongLength(); + Assert.assertEquals(size, result.getEncodedSize()); + + result.setObject("object-short", Short.MAX_VALUE); + size += 1 + EncodingUtils.encodedShortStringLength("object-short") + EncodingUtils.encodedShortLength(); + Assert.assertEquals(size, result.getEncodedSize()); + } + + /** + * Additional test for setObject + */ + public void testSetObject() + { + FieldTable table = new FieldTable(); + + // Try setting a non primative object + + try + { + table.setObject("value", this); + fail("Only primative values allowed in setObject"); + } + catch (AMQPInvalidClassException iae) + { + // normal path + } + // so length should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } + + /** + * Additional test checkPropertyName doesn't accept Null + */ + public void testCheckPropertyNameasNull() + { + FieldTable table = new FieldTable(); + + try + { + table.setObject((String) null, "String"); + fail("Null property name is not allowed"); + } + catch (IllegalArgumentException iae) + { + // normal path + } + // so length should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } + + /** + * Additional test checkPropertyName doesn't accept an empty String + */ + public void testCheckPropertyNameasEmptyString() + { + FieldTable table = new FieldTable(); + + try + { + table.setObject("", "String"); + fail("empty property name is not allowed"); + } + catch (IllegalArgumentException iae) + { + // normal path + } + // so length should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } + + /** + * Additional test checkPropertyName doesn't accept an empty String + */ + public void testCheckPropertyNamehasMaxLength() + { + FieldTable table = new FieldTable(true); + + StringBuffer longPropertyName = new StringBuffer(129); + + for (int i = 0; i < 129; i++) + { + longPropertyName.append("x"); + } + + try + { + table.setObject(longPropertyName.toString(), "String"); + fail("property name must be < 128 characters"); + } + catch (IllegalArgumentException iae) + { + // normal path + } + // so length should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } + + /** + * Additional test checkPropertyName starts with a letter + */ + public void testCheckPropertyNameStartCharacterIsLetter() + { + FieldTable table = new FieldTable(true); + + // Try a name that starts with a number + try + { + table.setObject("1", "String"); + fail("property name must start with a letter"); + } + catch (IllegalArgumentException iae) + { + // normal path + } + // so length should be zero + Assert.assertEquals(0, table.getEncodedSize()); + } + + /** + * Additional test checkPropertyName starts with a hash or a dollar + */ + public void testCheckPropertyNameStartCharacterIsHashorDollar() + { + FieldTable table = new FieldTable(true); + + // Try a name that starts with a number + try + { + table.setObject("#", "String"); + table.setObject("$", "String"); + } + catch (IllegalArgumentException iae) + { + fail("property name are allowed to start with # and $s"); + } + } + + /** + * Additional test to test the contents of the table + */ + public void testContents() + { + FieldTable table = new FieldTable(); + + table.setObject("StringProperty", "String"); + + Assert.assertEquals("String", table.getString("StringProperty")); + + // Test Clear + + table.clear(); + + checkEmpty(table); + } + + /** + * Test the contents of the sets + */ + public void testSets() + { + + FieldTable table = new FieldTable(); + + table.setObject("n1", "1"); + table.setObject("n2", "2"); + table.setObject("n3", "3"); + + Assert.assertEquals("1", table.getObject("n1")); + Assert.assertEquals("2", table.getObject("n2")); + Assert.assertEquals("3", table.getObject("n3")); + } + + public void testAddAll() + { + final FieldTable table1 = new FieldTable(); + table1.setInteger("int1", 1); + table1.setInteger("int2", 2); + assertEquals("Unexpected number of entries in table1", 2, table1.size()); + + final FieldTable table2 = new FieldTable(); + table2.setInteger("int3", 3); + table2.setInteger("int4", 4); + assertEquals("Unexpected number of entries in table2", 2, table2.size()); + + table1.addAll(table2); + assertEquals("Unexpected number of entries in table1 after addAll", 4, table1.size()); + assertEquals(Integer.valueOf(3), table1.getInteger("int3")); + } + + public void testAddAllWithEmptyFieldTable() + { + final FieldTable table1 = new FieldTable(); + table1.setInteger("int1", 1); + table1.setInteger("int2", 2); + assertEquals("Unexpected number of entries in table1", 2, table1.size()); + + final FieldTable emptyFieldTable = new FieldTable(); + + table1.addAll(emptyFieldTable); + assertEquals("Unexpected number of entries in table1 after addAll", 2, table1.size()); + } + + /** + * Tests that when copying properties into a new FielTable using the addAll() method, the + * properties are successfully added to the destination table when the source FieldTable + * was created from encoded input bytes, + */ + public void testAddingAllFromFieldTableCreatedUsingEncodedBytes() throws Exception + { + AMQShortString myBooleanTestProperty = new AMQShortString("myBooleanTestProperty"); + + //Create a new FieldTable and use it to encode data into a byte array. + FieldTable encodeTable = new FieldTable(); + encodeTable.put(myBooleanTestProperty, true); + byte[] data = encodeTable.getDataAsBytes(); + int length = data.length; + + //Verify we got the expected mount of encoded data (1B type hdr + 21B for name + 1B type hdr + 1B for boolean) + assertEquals("unexpected data length", 24, length); + + //Create a second FieldTable from the encoded bytes + FieldTable tableFromBytes = new FieldTable(new DataInputStream(new ByteArrayInputStream(data)), length); + + //Create a final FieldTable and addAll() from the table created with encoded bytes + FieldTable destinationTable = new FieldTable(); + assertTrue("unexpected size", destinationTable.isEmpty()); + destinationTable.addAll(tableFromBytes); + + //Verify that the destination table now contains the expected entry + assertEquals("unexpected size", 1, destinationTable.size()); + assertTrue("expected property not present", destinationTable.containsKey(myBooleanTestProperty)); + assertTrue("unexpected property value", destinationTable.getBoolean(myBooleanTestProperty)); + } + + private void assertBytesEqual(byte[] expected, byte[] actual) + { + Assert.assertEquals(expected.length, actual.length); + + for (int index = 0; index < expected.length; index++) + { + Assert.assertEquals(expected[index], actual[index]); + } + } + + public static junit.framework.Test suite() + { + return new junit.framework.TestSuite(FieldTableTest.class); + } + +} diff --git a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java deleted file mode 100644 index 16f35613d8..0000000000 --- a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java +++ /dev/null @@ -1,980 +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.framing; - -import junit.framework.Assert; -import junit.framework.TestCase; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.AMQPInvalidClassException; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -public class PropertyFieldTableTest extends TestCase -{ - private static final Logger _logger = LoggerFactory.getLogger(PropertyFieldTableTest.class); - - /** - * Test that setting a similar named value replaces any previous value set on that name - */ - public void testReplacement() - { - FieldTable table1 = new FieldTable(); - // Set a boolean value - table1.setBoolean("value", true); - // Check length of table is correct ( + + ) - int size = EncodingUtils.encodedShortStringLength("value") + 1 + EncodingUtils.encodedBooleanLength(); - Assert.assertEquals(size, table1.getEncodedSize()); - - // reset value to an integer - table1.setInteger("value", Integer.MAX_VALUE); - - // Check the length has changed accordingly ( + + ) - size = EncodingUtils.encodedShortStringLength("value") + 1 + EncodingUtils.encodedIntegerLength(); - Assert.assertEquals(size, table1.getEncodedSize()); - - // Check boolean value is null - Assert.assertEquals(null, table1.getBoolean("value")); - // ... and integer value is good - Assert.assertEquals((Integer) Integer.MAX_VALUE, table1.getInteger("value")); - } - - /** - * Set a boolean and check that we can only get it back as a boolean and a string - * Check that attempting to lookup a non existent value returns null - */ - public void testBoolean() - { - FieldTable table1 = new FieldTable(); - table1.setBoolean("value", true); - Assert.assertTrue(table1.propertyExists("value")); - - // Test Getting right value back - Assert.assertEquals((Boolean) true, table1.getBoolean("value")); - - // Check we don't get anything back for other gets - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(null, table1.getShort("value")); - Assert.assertEquals(null, table1.getCharacter("value")); - Assert.assertEquals(null, table1.getDouble("value")); - Assert.assertEquals(null, table1.getFloat("value")); - Assert.assertEquals(null, table1.getInteger("value")); - Assert.assertEquals(null, table1.getLong("value")); - Assert.assertEquals(null, table1.getBytes("value")); - - // except value as a string - Assert.assertEquals("true", table1.getString("value")); - - table1.remove("value"); - - // Table should now have zero length for encoding - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getBoolean("Rubbish")); - } - - /** - * Set a byte and check that we can only get it back as a byte and a string - * Check that attempting to lookup a non existent value returns null - */ - public void testByte() - { - FieldTable table1 = new FieldTable(); - table1.setByte("value", Byte.MAX_VALUE); - Assert.assertTrue(table1.propertyExists("value")); - - // Tests lookups we shouldn't get anything back for other gets - // we should get right value back for this type .... - Assert.assertEquals(null, table1.getBoolean("value")); - Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getByte("value")); - Assert.assertEquals(null, table1.getShort("value")); - Assert.assertEquals(null, table1.getCharacter("value")); - Assert.assertEquals(null, table1.getDouble("value")); - Assert.assertEquals(null, table1.getFloat("value")); - Assert.assertEquals(null, table1.getInteger("value")); - Assert.assertEquals(null, table1.getLong("value")); - Assert.assertEquals(null, table1.getBytes("value")); - - // ... and a the string value of it. - Assert.assertEquals("" + Byte.MAX_VALUE, table1.getString("value")); - - table1.remove("value"); - // Table should now have zero length for encoding - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getByte("Rubbish")); - } - - /** - * Set a short and check that we can only get it back as a short and a string - * Check that attempting to lookup a non existent value returns null - */ - public void testShort() - { - FieldTable table1 = new FieldTable(); - table1.setShort("value", Short.MAX_VALUE); - Assert.assertTrue(table1.propertyExists("value")); - - // Tests lookups we shouldn't get anything back for other gets - // we should get right value back for this type .... - Assert.assertEquals(null, table1.getBoolean("value")); - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(Short.MAX_VALUE, (short) table1.getShort("value")); - Assert.assertEquals(null, table1.getCharacter("value")); - Assert.assertEquals(null, table1.getDouble("value")); - Assert.assertEquals(null, table1.getFloat("value")); - Assert.assertEquals(null, table1.getInteger("value")); - Assert.assertEquals(null, table1.getLong("value")); - Assert.assertEquals(null, table1.getBytes("value")); - - // ... and a the string value of it. - Assert.assertEquals("" + Short.MAX_VALUE, table1.getString("value")); - - table1.remove("value"); - // Table should now have zero length for encoding - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getShort("Rubbish")); - } - - /** - * Set a char and check that we can only get it back as a char - * Check that attempting to lookup a non existent value returns null - */ - public void testChar() - { - FieldTable table1 = new FieldTable(); - table1.setChar("value", 'c'); - Assert.assertTrue(table1.propertyExists("value")); - - // Tests lookups we shouldn't get anything back for other gets - // we should get right value back for this type .... - Assert.assertEquals(null, table1.getBoolean("value")); - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(null, table1.getShort("value")); - Assert.assertEquals('c', (char) table1.getCharacter("value")); - Assert.assertEquals(null, table1.getDouble("value")); - Assert.assertEquals(null, table1.getFloat("value")); - Assert.assertEquals(null, table1.getInteger("value")); - Assert.assertEquals(null, table1.getLong("value")); - Assert.assertEquals(null, table1.getBytes("value")); - - // ... and a the string value of it. - Assert.assertEquals("c", table1.getString("value")); - - table1.remove("value"); - - // Table should now have zero length for encoding - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getCharacter("Rubbish")); - } - - /** - * Set a double and check that we can only get it back as a double - * Check that attempting to lookup a non existent value returns null - */ - public void testDouble() - { - FieldTable table1 = new FieldTable(); - table1.setDouble("value", Double.MAX_VALUE); - Assert.assertTrue(table1.propertyExists("value")); - - // Tests lookups we shouldn't get anything back for other gets - // we should get right value back for this type .... - Assert.assertEquals(null, table1.getBoolean("value")); - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(null, table1.getShort("value")); - Assert.assertEquals(null, table1.getCharacter("value")); - Assert.assertEquals(Double.MAX_VALUE, (double) table1.getDouble("value")); - Assert.assertEquals(null, table1.getFloat("value")); - Assert.assertEquals(null, table1.getInteger("value")); - Assert.assertEquals(null, table1.getLong("value")); - Assert.assertEquals(null, table1.getBytes("value")); - - // ... and a the string value of it. - Assert.assertEquals("" + Double.MAX_VALUE, table1.getString("value")); - table1.remove("value"); - // but after a removeKey it doesn't - Assert.assertFalse(table1.containsKey("value")); - - // Table should now have zero length for encoding - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getDouble("Rubbish")); - } - - /** - * Set a float and check that we can only get it back as a float - * Check that attempting to lookup a non existent value returns null - */ - public void testFloat() - { - FieldTable table1 = new FieldTable(); - table1.setFloat("value", Float.MAX_VALUE); - Assert.assertTrue(table1.propertyExists("value")); - - // Tests lookups we shouldn't get anything back for other gets - // we should get right value back for this type .... - Assert.assertEquals(null, table1.getBoolean("value")); - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(null, table1.getShort("value")); - Assert.assertEquals(null, table1.getCharacter("value")); - Assert.assertEquals(null, table1.getDouble("value")); - Assert.assertEquals(Float.MAX_VALUE, (float) table1.getFloat("value")); - Assert.assertEquals(null, table1.getInteger("value")); - Assert.assertEquals(null, table1.getLong("value")); - Assert.assertEquals(null, table1.getBytes("value")); - - // ... and a the string value of it. - Assert.assertEquals("" + Float.MAX_VALUE, table1.getString("value")); - - table1.remove("value"); - // but after a removeKey it doesn't - Assert.assertFalse(table1.containsKey("value")); - - // Table should now have zero length for encoding - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getFloat("Rubbish")); - } - - /** - * Set an int and check that we can only get it back as an int - * Check that attempting to lookup a non existent value returns null - */ - public void testInt() - { - FieldTable table1 = new FieldTable(); - table1.setInteger("value", Integer.MAX_VALUE); - Assert.assertTrue(table1.propertyExists("value")); - - // Tets lookups we shouldn't get anything back for other gets - // we should get right value back for this type .... - Assert.assertEquals(null, table1.getBoolean("value")); - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(null, table1.getShort("value")); - Assert.assertEquals(null, table1.getCharacter("value")); - Assert.assertEquals(null, table1.getDouble("value")); - Assert.assertEquals(null, table1.getFloat("value")); - Assert.assertEquals(Integer.MAX_VALUE, (int) table1.getInteger("value")); - Assert.assertEquals(null, table1.getLong("value")); - Assert.assertEquals(null, table1.getBytes("value")); - - // ... and a the string value of it. - Assert.assertEquals("" + Integer.MAX_VALUE, table1.getString("value")); - - table1.remove("value"); - // but after a removeKey it doesn't - Assert.assertFalse(table1.containsKey("value")); - - // Table should now have zero length for encoding - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getInteger("Rubbish")); - } - - /** - * Set a long and check that we can only get it back as a long - * Check that attempting to lookup a non existent value returns null - */ - public void testLong() - { - FieldTable table1 = new FieldTable(); - table1.setLong("value", Long.MAX_VALUE); - Assert.assertTrue(table1.propertyExists("value")); - - // Tets lookups we shouldn't get anything back for other gets - // we should get right value back for this type .... - Assert.assertEquals(null, table1.getBoolean("value")); - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(null, table1.getShort("value")); - Assert.assertEquals(null, table1.getCharacter("value")); - Assert.assertEquals(null, table1.getDouble("value")); - Assert.assertEquals(null, table1.getFloat("value")); - Assert.assertEquals(null, table1.getInteger("value")); - Assert.assertEquals(Long.MAX_VALUE, (long) table1.getLong("value")); - Assert.assertEquals(null, table1.getBytes("value")); - - // ... and a the string value of it. - Assert.assertEquals("" + Long.MAX_VALUE, table1.getString("value")); - - table1.remove("value"); - // but after a removeKey it doesn't - Assert.assertFalse(table1.containsKey("value")); - - // Table should now have zero length for encoding - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getLong("Rubbish")); - } - - /** - * Set a double and check that we can only get it back as a double - * Check that attempting to lookup a non existent value returns null - */ - public void testBytes() - { - byte[] bytes = { 99, 98, 97, 96, 95 }; - - FieldTable table1 = new FieldTable(); - table1.setBytes("value", bytes); - Assert.assertTrue(table1.propertyExists("value")); - - // Tets lookups we shouldn't get anything back for other gets - // we should get right value back for this type .... - Assert.assertEquals(null, table1.getBoolean("value")); - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(null, table1.getShort("value")); - Assert.assertEquals(null, table1.getCharacter("value")); - Assert.assertEquals(null, table1.getDouble("value")); - Assert.assertEquals(null, table1.getFloat("value")); - Assert.assertEquals(null, table1.getInteger("value")); - Assert.assertEquals(null, table1.getLong("value")); - assertBytesEqual(bytes, table1.getBytes("value")); - - // ... and a the string value of it is null - Assert.assertEquals(null, table1.getString("value")); - - table1.remove("value"); - // but after a removeKey it doesn't - Assert.assertFalse(table1.containsKey("value")); - - // Table should now have zero length for encoding - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getBytes("Rubbish")); - } - - /** - * Calls all methods that can be used to check the table is empty - * - getEncodedSize - * - isEmpty - * - length - * - * @param table to check is empty - */ - private void checkEmpty(FieldTable table) - { - Assert.assertEquals(0, table.getEncodedSize()); - Assert.assertTrue(table.isEmpty()); - Assert.assertEquals(0, table.size()); - - Assert.assertEquals(0, table.keySet().size()); - } - - /** - * Set a String and check that we can only get it back as a String - * Check that attempting to lookup a non existent value returns null - */ - public void testString() - { - FieldTable table1 = new FieldTable(); - table1.setString("value", "Hello"); - Assert.assertTrue(table1.propertyExists("value")); - - // Test lookups we shouldn't get anything back for other gets - // we should get right value back for this type .... - Assert.assertEquals(null, table1.getBoolean("value")); - Assert.assertEquals(null, table1.getByte("value")); - Assert.assertEquals(null, table1.getShort("value")); - Assert.assertEquals(null, table1.getCharacter("value")); - Assert.assertEquals(null, table1.getDouble("value")); - Assert.assertEquals(null, table1.getFloat("value")); - Assert.assertEquals(null, table1.getInteger("value")); - Assert.assertEquals(null, table1.getLong("value")); - Assert.assertEquals(null, table1.getBytes("value")); - Assert.assertEquals("Hello", table1.getString("value")); - - // Try setting a null value and read it back - table1.setString("value", null); - - Assert.assertEquals(null, table1.getString("value")); - - // but still contains the value - Assert.assertTrue(table1.containsKey("value")); - - table1.remove("value"); - // but after a removeKey it doesn't - Assert.assertFalse(table1.containsKey("value")); - - checkEmpty(table1); - - // Looking up an invalid value returns null - Assert.assertEquals(null, table1.getString("Rubbish")); - - // Additional Test that haven't been covered for string - table1.setObject("value", "Hello"); - // Check that it was set correctly - Assert.assertEquals("Hello", table1.getString("value")); - } - - /** Check that a nested field table parameter correctly encodes and decodes to a byte buffer. */ - public void testNestedFieldTable() throws IOException - { - byte[] testBytes = new byte[] { 0, 1, 2, 3, 4, 5 }; - - FieldTable outerTable = new FieldTable(); - FieldTable innerTable = new FieldTable(); - - // Put some stuff in the inner table. - innerTable.setBoolean("bool", true); - innerTable.setByte("byte", Byte.MAX_VALUE); - innerTable.setBytes("bytes", testBytes); - innerTable.setChar("char", 'c'); - innerTable.setDouble("double", Double.MAX_VALUE); - innerTable.setFloat("float", Float.MAX_VALUE); - innerTable.setInteger("int", Integer.MAX_VALUE); - innerTable.setLong("long", Long.MAX_VALUE); - innerTable.setShort("short", Short.MAX_VALUE); - innerTable.setString("string", "hello"); - innerTable.setString("null-string", null); - - // Put the inner table in the outer one. - outerTable.setFieldTable("innerTable", innerTable); - - // Write the outer table into the buffer. - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - outerTable.writeToBuffer(new DataOutputStream(baos)); - - byte[] data = baos.toByteArray(); - - // Extract the table back from the buffer again. - try - { - FieldTable extractedOuterTable = EncodingUtils.readFieldTable(new DataInputStream(new ByteArrayInputStream(data))); - - FieldTable extractedTable = extractedOuterTable.getFieldTable("innerTable"); - - Assert.assertEquals((Boolean) true, extractedTable.getBoolean("bool")); - Assert.assertEquals((Byte) Byte.MAX_VALUE, extractedTable.getByte("byte")); - assertBytesEqual(testBytes, extractedTable.getBytes("bytes")); - Assert.assertEquals((Character) 'c', extractedTable.getCharacter("char")); - Assert.assertEquals(Double.MAX_VALUE, extractedTable.getDouble("double")); - Assert.assertEquals(Float.MAX_VALUE, extractedTable.getFloat("float")); - Assert.assertEquals((Integer) Integer.MAX_VALUE, extractedTable.getInteger("int")); - Assert.assertEquals((Long) Long.MAX_VALUE, extractedTable.getLong("long")); - Assert.assertEquals((Short) Short.MAX_VALUE, extractedTable.getShort("short")); - Assert.assertEquals("hello", extractedTable.getString("string")); - Assert.assertEquals(null, extractedTable.getString("null-string")); - } - catch (AMQFrameDecodingException e) - { - fail("Failed to decode field table with nested inner table."); - } - } - - public void testValues() - { - FieldTable table = new FieldTable(); - table.setBoolean("bool", true); - table.setByte("byte", Byte.MAX_VALUE); - byte[] bytes = { 99, 98, 97, 96, 95 }; - table.setBytes("bytes", bytes); - table.setChar("char", 'c'); - table.setDouble("double", Double.MAX_VALUE); - table.setFloat("float", Float.MAX_VALUE); - table.setInteger("int", Integer.MAX_VALUE); - table.setLong("long", Long.MAX_VALUE); - table.setShort("short", Short.MAX_VALUE); - table.setString("string", "Hello"); - table.setString("null-string", null); - - table.setObject("object-bool", true); - table.setObject("object-byte", Byte.MAX_VALUE); - table.setObject("object-bytes", bytes); - table.setObject("object-char", 'c'); - table.setObject("object-double", Double.MAX_VALUE); - table.setObject("object-float", Float.MAX_VALUE); - table.setObject("object-int", Integer.MAX_VALUE); - table.setObject("object-long", Long.MAX_VALUE); - table.setObject("object-short", Short.MAX_VALUE); - table.setObject("object-string", "Hello"); - - try - { - table.setObject("Null-object", null); - fail("null values are not allowed"); - } - catch (AMQPInvalidClassException aice) - { - assertEquals("Null values are not allowed to be set", - AMQPInvalidClassException.INVALID_OBJECT_MSG + "null", aice.getMessage()); - } - - try - { - table.setObject("Unsupported-object", new Exception()); - fail("Non primitive values are not allowed"); - } - catch (AMQPInvalidClassException aice) - { - assertEquals("Non primitive values are not allowed to be set", - AMQPInvalidClassException.INVALID_OBJECT_MSG + Exception.class, aice.getMessage()); - } - - Assert.assertEquals((Boolean) true, table.getBoolean("bool")); - Assert.assertEquals((Byte) Byte.MAX_VALUE, table.getByte("byte")); - assertBytesEqual(bytes, table.getBytes("bytes")); - Assert.assertEquals((Character) 'c', table.getCharacter("char")); - Assert.assertEquals(Double.MAX_VALUE, table.getDouble("double")); - Assert.assertEquals(Float.MAX_VALUE, table.getFloat("float")); - Assert.assertEquals((Integer) Integer.MAX_VALUE, table.getInteger("int")); - Assert.assertEquals((Long) Long.MAX_VALUE, table.getLong("long")); - Assert.assertEquals((Short) Short.MAX_VALUE, table.getShort("short")); - Assert.assertEquals("Hello", table.getString("string")); - Assert.assertEquals(null, table.getString("null-string")); - - Assert.assertEquals(true, table.getObject("object-bool")); - Assert.assertEquals(Byte.MAX_VALUE, table.getObject("object-byte")); - assertBytesEqual(bytes, (byte[]) table.getObject("object-bytes")); - Assert.assertEquals('c', table.getObject("object-char")); - Assert.assertEquals(Double.MAX_VALUE, table.getObject("object-double")); - Assert.assertEquals(Float.MAX_VALUE, table.getObject("object-float")); - Assert.assertEquals(Integer.MAX_VALUE, table.getObject("object-int")); - Assert.assertEquals(Long.MAX_VALUE, table.getObject("object-long")); - Assert.assertEquals(Short.MAX_VALUE, table.getObject("object-short")); - Assert.assertEquals("Hello", table.getObject("object-string")); - } - - public void testWriteBuffer() throws IOException - { - byte[] bytes = { 99, 98, 97, 96, 95 }; - - FieldTable table = new FieldTable(); - table.setBoolean("bool", true); - table.setByte("byte", Byte.MAX_VALUE); - - table.setBytes("bytes", bytes); - table.setChar("char", 'c'); - table.setInteger("int", Integer.MAX_VALUE); - table.setLong("long", Long.MAX_VALUE); - table.setDouble("double", Double.MAX_VALUE); - table.setFloat("float", Float.MAX_VALUE); - table.setShort("short", Short.MAX_VALUE); - table.setString("string", "hello"); - table.setString("null-string", null); - - - ByteArrayOutputStream baos = new ByteArrayOutputStream((int) table.getEncodedSize() + 4); - table.writeToBuffer(new DataOutputStream(baos)); - - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - DataInputStream dis = new DataInputStream(bais); - - - long length = dis.readInt() & 0xFFFFFFFFL; - - FieldTable table2 = new FieldTable(dis, length); - - Assert.assertEquals((Boolean) true, table2.getBoolean("bool")); - Assert.assertEquals((Byte) Byte.MAX_VALUE, table2.getByte("byte")); - assertBytesEqual(bytes, table2.getBytes("bytes")); - Assert.assertEquals((Character) 'c', table2.getCharacter("char")); - Assert.assertEquals(Double.MAX_VALUE, table2.getDouble("double")); - Assert.assertEquals(Float.MAX_VALUE, table2.getFloat("float")); - Assert.assertEquals((Integer) Integer.MAX_VALUE, table2.getInteger("int")); - Assert.assertEquals((Long) Long.MAX_VALUE, table2.getLong("long")); - Assert.assertEquals((Short) Short.MAX_VALUE, table2.getShort("short")); - Assert.assertEquals("hello", table2.getString("string")); - Assert.assertEquals(null, table2.getString("null-string")); - } - - public void testEncodingSize() - { - FieldTable result = new FieldTable(); - int size = 0; - - result.setBoolean("boolean", true); - size += 1 + EncodingUtils.encodedShortStringLength("boolean") + EncodingUtils.encodedBooleanLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setByte("byte", (byte) Byte.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("byte") + EncodingUtils.encodedByteLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - byte[] _bytes = { 99, 98, 97, 96, 95 }; - - result.setBytes("bytes", _bytes); - size += 1 + EncodingUtils.encodedShortStringLength("bytes") + 4 + _bytes.length; - Assert.assertEquals(size, result.getEncodedSize()); - - result.setChar("char", (char) 'c'); - size += 1 + EncodingUtils.encodedShortStringLength("char") + EncodingUtils.encodedCharLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setDouble("double", (double) Double.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("double") + EncodingUtils.encodedDoubleLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setFloat("float", (float) Float.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("float") + EncodingUtils.encodedFloatLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setInteger("int", (int) Integer.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("int") + EncodingUtils.encodedIntegerLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setLong("long", (long) Long.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("long") + EncodingUtils.encodedLongLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setShort("short", (short) Short.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("short") + EncodingUtils.encodedShortLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setString("result", "Hello"); - size += 1 + EncodingUtils.encodedShortStringLength("result") + EncodingUtils.encodedLongStringLength("Hello"); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setObject("object-bool", true); - size += 1 + EncodingUtils.encodedShortStringLength("object-bool") + EncodingUtils.encodedBooleanLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setObject("object-byte", Byte.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("object-byte") + EncodingUtils.encodedByteLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setObject("object-bytes", _bytes); - size += 1 + EncodingUtils.encodedShortStringLength("object-bytes") + 4 + _bytes.length; - Assert.assertEquals(size, result.getEncodedSize()); - - result.setObject("object-char", 'c'); - size += 1 + EncodingUtils.encodedShortStringLength("object-char") + EncodingUtils.encodedCharLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setObject("object-double", Double.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("object-double") + EncodingUtils.encodedDoubleLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setObject("object-float", Float.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("object-float") + EncodingUtils.encodedFloatLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setObject("object-int", Integer.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("object-int") + EncodingUtils.encodedIntegerLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setObject("object-long", Long.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("object-long") + EncodingUtils.encodedLongLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - result.setObject("object-short", Short.MAX_VALUE); - size += 1 + EncodingUtils.encodedShortStringLength("object-short") + EncodingUtils.encodedShortLength(); - Assert.assertEquals(size, result.getEncodedSize()); - - } - - // public void testEncodingSize1() - // { - // PropertyFieldTable table = new PropertyFieldTable(); - // int length = 0; - // result.put("one", 1L); - // length = EncodingUtils.encodedShortStringLength("one"); - // length += 1 + EncodingUtils.encodedLongLength(); - // assertEquals(length, result.getEncodedSize()); - // - // result.put("two", 2L); - // length += EncodingUtils.encodedShortStringLength("two"); - // length += 1 + EncodingUtils.encodedLongLength(); - // assertEquals(length, result.getEncodedSize()); - // - // result.put("three", 3L); - // length += EncodingUtils.encodedShortStringLength("three"); - // length += 1 + EncodingUtils.encodedLongLength(); - // assertEquals(length, result.getEncodedSize()); - // - // result.put("four", 4L); - // length += EncodingUtils.encodedShortStringLength("four"); - // length += 1 + EncodingUtils.encodedLongLength(); - // assertEquals(length, result.getEncodedSize()); - // - // result.put("five", 5L); - // length += EncodingUtils.encodedShortStringLength("five"); - // length += 1 + EncodingUtils.encodedLongLength(); - // assertEquals(length, result.getEncodedSize()); - // - // //fixme should perhaps be expanded to incorporate all types. - // - // final ByteBuffer buffer = ByteBuffer.allocate((int) result.getEncodedSize()); // FIXME XXX: Is cast a problem? - // - // result.writeToBuffer(buffer); - // - // buffer.flip(); - // - // long length = buffer.getUnsignedInt(); - // - // try - // { - // PropertyFieldTable table2 = new PropertyFieldTable(buffer, length); - // - // Assert.assertEquals((Long) 1L, table2.getLong("one")); - // Assert.assertEquals((Long) 2L, table2.getLong("two")); - // Assert.assertEquals((Long) 3L, table2.getLong("three")); - // Assert.assertEquals((Long) 4L, table2.getLong("four")); - // Assert.assertEquals((Long) 5L, table2.getLong("five")); - // } - // catch (AMQFrameDecodingException e) - // { - // e.printStackTrace(); - // fail("PFT should be instantiated from bytes." + e.getCause()); - // } - // - // } - - /** - * Additional test for setObject - */ - public void testSetObject() - { - FieldTable table = new FieldTable(); - - // Try setting a non primative object - - try - { - table.setObject("value", this); - fail("Only primative values allowed in setObject"); - } - catch (AMQPInvalidClassException iae) - { - // normal path - } - // so length should be zero - Assert.assertEquals(0, table.getEncodedSize()); - } - - /** - * Additional test checkPropertyName doesn't accept Null - */ - public void testCheckPropertyNameasNull() - { - FieldTable table = new FieldTable(); - - try - { - table.setObject((String) null, "String"); - fail("Null property name is not allowed"); - } - catch (IllegalArgumentException iae) - { - // normal path - } - // so length should be zero - Assert.assertEquals(0, table.getEncodedSize()); - } - - /** - * Additional test checkPropertyName doesn't accept an empty String - */ - public void testCheckPropertyNameasEmptyString() - { - FieldTable table = new FieldTable(); - - try - { - table.setObject("", "String"); - fail("empty property name is not allowed"); - } - catch (IllegalArgumentException iae) - { - // normal path - } - // so length should be zero - Assert.assertEquals(0, table.getEncodedSize()); - } - - /** - * Additional test checkPropertyName doesn't accept an empty String - */ - public void testCheckPropertyNamehasMaxLength() - { - FieldTable table = new FieldTable(true); - - StringBuffer longPropertyName = new StringBuffer(129); - - for (int i = 0; i < 129; i++) - { - longPropertyName.append("x"); - } - - try - { - table.setObject(longPropertyName.toString(), "String"); - fail("property name must be < 128 characters"); - } - catch (IllegalArgumentException iae) - { - // normal path - } - // so length should be zero - Assert.assertEquals(0, table.getEncodedSize()); - } - - /** - * Additional test checkPropertyName starts with a letter - */ - public void testCheckPropertyNameStartCharacterIsLetter() - { - FieldTable table = new FieldTable(true); - - // Try a name that starts with a number - try - { - table.setObject("1", "String"); - fail("property name must start with a letter"); - } - catch (IllegalArgumentException iae) - { - // normal path - } - // so length should be zero - Assert.assertEquals(0, table.getEncodedSize()); - } - - /** - * Additional test checkPropertyName starts with a hash or a dollar - */ - public void testCheckPropertyNameStartCharacterIsHashorDollar() - { - FieldTable table = new FieldTable(true); - - // Try a name that starts with a number - try - { - table.setObject("#", "String"); - table.setObject("$", "String"); - } - catch (IllegalArgumentException iae) - { - fail("property name are allowed to start with # and $s"); - } - - } - - /** - * Additional test to test the contents of the table - */ - public void testContents() - { - FieldTable table = new FieldTable(); - - table.setObject("StringProperty", "String"); - - Assert.assertEquals("String", table.getString("StringProperty")); - - // Test Clear - - table.clear(); - - checkEmpty(table); - } - - /** - * Test the contents of the sets - */ - public void testSets() - { - - FieldTable table = new FieldTable(); - - table.setObject("n1", "1"); - table.setObject("n2", "2"); - table.setObject("n3", "3"); - - Assert.assertEquals("1", table.getObject("n1")); - Assert.assertEquals("2", table.getObject("n2")); - Assert.assertEquals("3", table.getObject("n3")); - - } - - public void testAddAll() - { - final FieldTable table1 = new FieldTable(); - table1.setInteger("int1", 1); - table1.setInteger("int2", 2); - assertEquals("Unexpected number of entries in table1", 2, table1.size()); - - final FieldTable table2 = new FieldTable(); - table2.setInteger("int3", 3); - table2.setInteger("int4", 4); - assertEquals("Unexpected number of entries in table2", 2, table2.size()); - - table1.addAll(table2); - assertEquals("Unexpected number of entries in table1 after addAll", 4, table1.size()); - assertEquals(Integer.valueOf(3), table1.getInteger("int3")); - } - - public void testAddAllWithEmptyFieldTable() - { - final FieldTable table1 = new FieldTable(); - table1.setInteger("int1", 1); - table1.setInteger("int2", 2); - assertEquals("Unexpected number of entries in table1", 2, table1.size()); - - final FieldTable emptyFieldTable = new FieldTable(); - - table1.addAll(emptyFieldTable); - assertEquals("Unexpected number of entries in table1 after addAll", 2, table1.size()); - } - - private void assertBytesEqual(byte[] expected, byte[] actual) - { - Assert.assertEquals(expected.length, actual.length); - - for (int index = 0; index < expected.length; index++) - { - Assert.assertEquals(expected[index], actual[index]); - } - } - - private void assertBytesNotEqual(byte[] expected, byte[] actual) - { - Assert.assertEquals(expected.length, actual.length); - - for (int index = 0; index < expected.length; index++) - { - Assert.assertFalse(expected[index] == actual[index]); - } - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(PropertyFieldTableTest.class); - } - -} diff --git a/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java b/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java index ec06400b7d..08f7387b75 100644 --- a/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java +++ b/java/common/src/test/java/org/apache/qpid/test/utils/QpidTestCase.java @@ -41,6 +41,7 @@ public class QpidTestCase extends TestCase public static final String QPID_HOME = System.getProperty("QPID_HOME"); public static final String TEST_RESOURCES_DIR = QPID_HOME + "/../test-profiles/test_resources/"; public static final String TMP_FOLDER = System.getProperty("java.io.tmpdir"); + public static final String LOG4J_CONFIG_FILE_PATH = System.getProperty("log4j.configuration.file"); private static final Logger _logger = Logger.getLogger(QpidTestCase.class); @@ -115,12 +116,7 @@ public class QpidTestCase extends TestCase public QpidTestCase() { - this("QpidTestCase"); - } - - public QpidTestCase(String name) - { - super(name); + super(); } public void run(TestResult testResult) @@ -204,6 +200,8 @@ public class QpidTestCase extends TestCase { System.setProperty(property, value); } + + _logger.info("Set system property \"" + property + "\" to: \"" + value + "\""); } /** diff --git a/java/common/src/test/java/org/apache/qpid/test/utils/TestFileUtils.java b/java/common/src/test/java/org/apache/qpid/test/utils/TestFileUtils.java index 056d11faaa..14dec8efad 100644 --- a/java/common/src/test/java/org/apache/qpid/test/utils/TestFileUtils.java +++ b/java/common/src/test/java/org/apache/qpid/test/utils/TestFileUtils.java @@ -21,6 +21,12 @@ package org.apache.qpid.test.utils; import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +import java.io.FileOutputStream; + +import junit.framework.TestCase; import org.apache.qpid.util.FileUtils; @@ -30,6 +36,7 @@ import org.apache.qpid.util.FileUtils; public class TestFileUtils { private static final String SYSTEM_TMP_DIR = System.getProperty("java.io.tmpdir"); + private static final String SUFFIX = "tmp"; /** * Create and return a temporary directory that will be deleted on exit. @@ -60,4 +67,87 @@ public class TestFileUtils return testDir; } + + public static File createTempFile(TestCase testcase) + { + return createTempFile(testcase, SUFFIX); + } + + public static File createTempFile(TestCase testcase, String suffix) + { + String prefix = testcase.getClass().getSimpleName() + "-" + testcase.getName(); + + File tmpFile; + try + { + tmpFile = File.createTempFile(prefix, suffix); + tmpFile.deleteOnExit(); + } + catch (IOException e) + { + throw new RuntimeException("Cannot create temporary file with prefix " + prefix + " and suffix " + SUFFIX, e); + } + + return tmpFile; + } + + /** + * Creates a temporary file from the resource name given, using the resource name as the file suffix. + * + * This is required because the tests use the jar files as their class path. + */ + public static File createTempFileFromResource(TestCase testCase, String resourceName) + { + File dst = createTempFile(testCase, resourceName); + InputStream in = testCase.getClass().getResourceAsStream(resourceName); + try + { + FileUtils.copy(in, dst); + } + catch (Exception e) + { + throw new RuntimeException("Cannot copy resource " + resourceName + + " to temp file " + dst.getAbsolutePath(), e); + } + dst.deleteOnExit(); + return dst; + } + + /** + * Creates a temporary file for given test with given suffix in file name. + * The given content is stored in the file using UTF-8 encoding. + */ + public static File createTempFile(TestCase testcase, String suffix, String content) + { + File file = createTempFile(testcase, suffix); + if (content != null) + { + FileOutputStream fos = null; + try + { + fos = new FileOutputStream(file); + fos.write(content.getBytes("UTF-8")); + fos.flush(); + } + catch (Exception e) + { + throw new RuntimeException("Cannot add the content into temp file " + file.getAbsolutePath(), e); + } + finally + { + if (fos != null) + { + try + { + fos.close(); + } + catch (IOException e) + { + throw new RuntimeException("Cannot close output stream into temp file " + file.getAbsolutePath(), e); + } + } + } + } + return file; + } } diff --git a/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java index f3715f351e..12bbd20228 100644 --- a/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java +++ b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java @@ -155,6 +155,7 @@ public class ConnectionTest extends QpidTestCase implements SessionListener { final Connection conn = new Connection(); conn.setConnectionDelegate(new ClientDelegate(new ConnectionSettings())); + conn.addConnectionListener(new ConnectionListener() { public void opened(Connection conn) {} @@ -225,6 +226,12 @@ public class ConnectionTest extends QpidTestCase implements SessionListener ssn.setSessionListener(ConnectionTest.this); return ssn; } + + @Override + public void connectionStartOk(Connection conn, ConnectionStartOk ok) + { + tuneAuthorizedConnection(conn); + } }; try diff --git a/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java b/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java index 893f66c5ff..a19c2e7e43 100644 --- a/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java +++ b/java/common/src/test/java/org/apache/qpid/transport/TestNetworkConnection.java @@ -83,6 +83,18 @@ public class TestNetworkConnection implements NetworkConnection return null; } + @Override + public int getMaxReadIdle() + { + return 0; + } + + @Override + public int getMaxWriteIdle() + { + return 0; + } + public void setMaxWriteIdle(int idleTime) { diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java b/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java index c882d3437e..bf9a5843d6 100644 --- a/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java +++ b/java/common/src/test/java/org/apache/qpid/transport/network/TransportTest.java @@ -128,7 +128,8 @@ public class TransportTest extends QpidTestCase } public NetworkConnection connect(ConnectionSettings settings, - Receiver delegate, SSLContext sslContext) + Receiver delegate, + TransportActivity transportActivity) { throw new UnsupportedOperationException(); } @@ -148,7 +149,7 @@ public class TransportTest extends QpidTestCase } public void accept(NetworkTransportConfiguration config, - ProtocolEngineFactory factory, SSLContext sslContext) + ProtocolEngineFactory factory, SSLContext sslContext) { throw new UnsupportedOperationException(); } diff --git a/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java b/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java new file mode 100644 index 0000000000..5cdd7a8597 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java @@ -0,0 +1,257 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.transport.network.io; + +import junit.framework.TestCase; + +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.security.Principal; + +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.transport.network.TransportActivity; + +public class IdleTimeoutTickerTest extends TestCase implements TransportActivity, NetworkConnection +{ + private IdleTimeoutTicker _ticker; + private static final int DEFAULT_TIMEOUT = 567890; + private long _lastReadTime; + private long _lastWriteTime; + private long _currentTime; + private int _maxWriteIdle; + private int _maxReadIdle; + private boolean _readerIdle; + private boolean _writerIdle; + + @Override + public void setUp() throws Exception + { + super.setUp(); + _ticker = new IdleTimeoutTicker(this, DEFAULT_TIMEOUT); + _ticker.setConnection(this); + _readerIdle = false; + _writerIdle = false; + _lastReadTime = 0l; + _lastWriteTime = 0l; + _maxReadIdle = 0; + _maxWriteIdle = 0; + } + + public void testNoIdle() throws Exception + { + _maxReadIdle = 4; + _maxWriteIdle = 2; + _lastReadTime = 0; + _lastWriteTime = 1500; + _currentTime = 3000; + // Current time = 3s, + // last read = 0s, max read idle = 4s, should check in 1s + // last write = 1.5s, max write idle = 2s, should check in 0.5s + long nextTime = _ticker.tick(_currentTime); + assertEquals("Incorrect next tick calculation", 500l, nextTime); + assertFalse("Incorrectly caused reader idle", _readerIdle); + assertFalse("Incorrectly caused writer idle", _writerIdle); + + + // Current time = 3.4s, + // last read = 0s, max read idle = 4s, should check in 0.6s + // last write = 3.1s, max write idle = 2s, should check in 1.7s + _lastWriteTime = 3100; + _currentTime = 3400; + nextTime = _ticker.tick(_currentTime); + assertEquals("Incorrect next tick calculation", 600l, nextTime); + assertFalse("Incorrectly caused reader idle", _readerIdle); + assertFalse("Incorrectly caused writer idle", _writerIdle); + + _maxReadIdle = 0; + nextTime = _ticker.tick(_currentTime); + assertEquals("Incorrect next tick calculation", 1700l, nextTime); + assertFalse("Incorrectly caused reader idle", _readerIdle); + assertFalse("Incorrectly caused writer idle", _writerIdle); + + _maxWriteIdle = 0; + nextTime = _ticker.tick(_currentTime); + assertEquals("Incorrect next tick calculation", DEFAULT_TIMEOUT, nextTime); + assertFalse("Incorrectly caused reader idle", _readerIdle); + assertFalse("Incorrectly caused writer idle", _writerIdle); + + } + + public void testReaderIdle() throws Exception + { + _maxReadIdle = 4; + _maxWriteIdle = 0; + _lastReadTime = 0; + _lastWriteTime = 2500; + _currentTime = 4000; + // Current time = 4s, + // last read = 0s, max read idle = 4s, reader idle + long nextTime = _ticker.tick(_currentTime); + + assertTrue(_readerIdle); + assertFalse(_writerIdle); + + _readerIdle = false; + + // last write = 2.5s, max write idle = 2s, should check in 0.5s + _maxWriteIdle = 2; + nextTime = _ticker.tick(_currentTime); + assertTrue(_readerIdle); + assertFalse(_writerIdle); + + _readerIdle = false; + // last write = 1.5s, max write idle = 2s, should check in 0.5s + + _lastWriteTime = 1500; + nextTime = _ticker.tick(_currentTime); + + assertTrue(_readerIdle); + assertTrue(_writerIdle); + + } + + public void testWriterIdle() throws Exception + { + _maxReadIdle = 0; + _maxWriteIdle = 2; + _lastReadTime = 0; + _lastWriteTime = 1500; + _currentTime = 4000; + // Current time = 4s, + // last write = 1.5s, max write idle = 2s, writer idle + long nextTime = _ticker.tick(_currentTime); + + assertTrue(_writerIdle); + assertFalse(_readerIdle); + assertEquals(2000l,nextTime); + + _writerIdle = false; + _lastWriteTime = 1500; + _maxReadIdle = 5; + + nextTime = _ticker.tick(_currentTime); + + assertTrue(_writerIdle); + assertFalse(_readerIdle); + assertEquals(1000l,nextTime); + + } + + //------------------------------------------------------------------------- + // Implement TransportActivity methods + //------------------------------------------------------------------------- + + @Override + public long getLastReadTime() + { + return _lastReadTime; + } + + @Override + public long getLastWriteTime() + { + return _lastWriteTime; + } + + @Override + public void writerIdle() + { + _writerIdle = true; + _lastWriteTime = _currentTime; + } + + @Override + public void readerIdle() + { + _readerIdle = true; + } + + //------------------------------------------------------------------------- + // Implement NetworkConnection methods + // Only actually use those relating to idle timeouts + //------------------------------------------------------------------------- + + @Override + public Sender getSender() + { + return null; + } + + @Override + public void start() + { + } + + @Override + public void close() + { + } + + @Override + public SocketAddress getRemoteAddress() + { + return null; + } + + @Override + public SocketAddress getLocalAddress() + { + return null; + } + + @Override + public void setMaxWriteIdle(int sec) + { + _maxWriteIdle = sec; + } + + @Override + public void setMaxReadIdle(int sec) + { + _maxReadIdle = sec; + } + + @Override + public void setPeerPrincipal(Principal principal) + { + } + + @Override + public Principal getPeerPrincipal() + { + return null; + } + + @Override + public int getMaxReadIdle() + { + return _maxReadIdle; + } + + @Override + public int getMaxWriteIdle() + { + return _maxWriteIdle; + } +} diff --git a/java/ivy.nexus.xml b/java/ivy.nexus.xml index 61ae9f315b..c39f466da3 100644 --- a/java/ivy.nexus.xml +++ b/java/ivy.nexus.xml @@ -39,6 +39,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -51,6 +87,12 @@ + + + + + + diff --git a/java/ivy.retrieve.xml b/java/ivy.retrieve.xml index 3af847a48a..5998a3e78e 100644 --- a/java/ivy.retrieve.xml +++ b/java/ivy.retrieve.xml @@ -57,7 +57,6 @@ - @@ -70,6 +69,8 @@ + + - + diff --git a/java/jca/README-JBOSS-EAP6.txt b/java/jca/README-JBOSS-EAP6.txt new file mode 100644 index 0000000000..219bfb6468 --- /dev/null +++ b/java/jca/README-JBOSS-EAP6.txt @@ -0,0 +1,183 @@ +Qpid JCA Resource Adapter + +JBoss EAP 6.x Installation and Configuration Instructions + +Overview +======== +The Qpid Resource Adapter is a JCA 1.5 compliant resource adapter that allows +for JEE integration between EE applications and AMQP 0.10 message brokers. + +The adapter provides both outbound and inbound connectivity and +exposes a variety of options to fine tune your messaging applications. +Currently the adapter only supports C++ based brokers and has only been tested with Apache Qpid C++ broker. + +The following document explains how to configure the resource adapter for deployment in JBoss EAP 6.x. + +Deployment +========== +To deploy the Qpid JCA adapter in the JBoss EAP 6 environment, copy the qpid-ra-.rar file +to your JBoss deployment directory. By default this can be found at + +JBOSS_ROOT//deployments + +where JBOSS_ROOT denotes the root directory of your JBoss EAP 6.x installation and denotes the +particular server configuration for your applicationd development. Currently, JBoss EAP 6 provides two configurations +by default standalone and domain. This documentation assumes the standalone server configuration, though the process +to configure and deploy the Qpid JCA adapter is largely the same between the two. Assuming the standalone configuration +the deployment location above would be + +JBOSS_ROOT/standalone/deployments + +Note, as opposed to prior versions of EAP, copying a RAR file to the deployment location does not automatically +start and deploy the adapter. A separate manual configuration step is required which is explained in the following +section. + +Configuration +============= +The EAP 6.x environment uses an XML based configuration scheme that is fundamentally different than prior versions +of EAP. As previously mentioned, EAP 6.x provides two server configuration types, standalone and domain. Each come with +a different set of configuration files that are tailored to varying types of server environments. Configuration locations +can be found at + +JBOSS_ROOT//configuration + +The varying XML files are named + +-full.xml +-full-ha.xml +.xml + +where each XML file denotes the capabilites of the server. This document assumes a minimal server configuration in +the standalone server environment. While each configuration file provides a variety of options, this document is +only concerned with the configuration of the JCA adapter. Please consult the EAP 6.x documentation for other +options and configuration scenarios. + +The EAP 6.x infrastructure is built upon the notion of varying subsystem where subsystem generally corresponds +to one particular piece of functionality. Typical examples are EJB, JAXR etc. In order to configure the Qpid JCA adapter +we need to modify the ejb and resource-adapters subsystems in order to tell EAP 6.x about our RAR deployment as well +as the RAR that will provide JMS provider functionality. + +Note, JCA in EAP 6.x involves two subsystems, jca and resource-adapters. The former subsytem provides capabilities for +all JCA deployments (the JCA runtime environment) where the resource-adapters subsystem is particular to an invidual JCA +deployment. Here we are only concerned with the latter. Please consult the EAP 6.x documentation for more general JCA +configuration options as well as other subsystems. + +Each subsystem is configured in an XML fragment and is versioned separately. Subsystem versions will change over +time so this document may not reflect the most current version, but the Qpid JCA configuration options remain +unchanged across subsystem regardless of version or release date. + +The following XML fragment replaces the default messaging provider in the EAP 6.x environment + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +The only real lines we are concerned with are + + + + + + +however, the complete fragment is provided for clarity. + +The following XML fragment provides a minimal example configuration in the EAP 6 environment. Here we are configuring +an XA aware ManagedConnectionFactory and two JMS destinations (queue and topic) + + + + + + qpid-ra-.rar + + + XATransaction + + + amqp://anonymous:passwd@client/test?brokerlist='tcp://localhost?sasl_mechs='PLAIN'' + + + org.apache.qpid.ra.tm.JBoss7TransactionManagerLocator + + + getTm + + + + + amqp://anonymous:passwd@client/test?brokerlist='tcp://localhost?sasl_mechs='PLAIN'' + + + javax.jms.Queue + + + + + + + amq.topic/hello.Topic + + + + + hello.Queue;{create:always, node:{type:queue, x-declare:{auto-delete:true}}} + + + + + + + + + +Note, while this document assumes that you are modifying the standalone.xml file directly, an alternative to this approach would be +to make a copy of the file, apply the modifications above and start the EAP instance with the new configuration + +JBOSS_HOME/bin/standalone.sh -c your-modified-config.xml + +Regardless of the approach that you use, once the modifications have been made you can start your EAP 6.x instance and the Qpid JCA +adapter will be deployed and ready for use. If property deployed and configured, you should see something in the log files or console +resembling the following: + +INFO [org.apache.qpid.ra.QpidResourceAdapter] (MSC service thread 1-4) Qpid resource adapter started + + +Notes +===== +While the differences between the EAP 5.x and 6.x environments may appear to be dramatic, the configuration options and functionality of the Qpid +JCA adapter are not. The README.txt file outlines general configuration options that remain unchanged between the respective EAP environments. + diff --git a/java/jca/README-JBOSS.txt b/java/jca/README-JBOSS.txt index 77bf91e6dd..e88643e0f2 100644 --- a/java/jca/README-JBOSS.txt +++ b/java/jca/README-JBOSS.txt @@ -61,7 +61,7 @@ XA ConnectionFactory qpid-ra-.rar org.apache.qpid.ra.QpidRAConnectionFactory - amqp://guest:guest@/test?brokerlist='tcp://localhost:5672?sasl_mechs='ANONYMOUS'' + amqp://guest:guest@/test?brokerlist='tcp://localhost:5672?sasl_mechs='PLAIN'' 20 @@ -79,11 +79,11 @@ Local ConnectionFactory ======================= QpidJMS - qpid-ra-0.10.rar + qpid-ra-.rar - true - amqp://anonymous:@client/test?brokerlist='tcp://localhost:5672?sasl_mechs='ANONYMOUS'' - org.apache.qpid.ra.QpidRAConnectionFactory + true + amqp://anonymous:@client/test?brokerlist='tcp://localhost:5672?sasl_mechs='PLAIN'' + org.apache.qpid.ra.QpidRAConnectionFactory 20 @@ -100,11 +100,10 @@ provides two such objects Hello - jboss.jca:service=RARDeployment,name='qpid-ra-0.10.rar' + jboss.jca:service=RARDeployment,name='qpid-ra-.rar' javax.jms.Destination - destinationType=QUEUE - destinationAddress=amq.direct + DestinationAddress=amq.direct @@ -113,16 +112,15 @@ The above XML defines a JMS Queue which is bound into JNDI as queue/HelloQueue This destination can be retrieved from JNDI and be used for the consumption or production of messages. The desinationAddress property -can be customized for your environment. Please see the Qpid Java Client documentation for specific configuration options. +can be customized for your environment. Please see the Qpid Java Client documentation for specific configuration options. HelloTopic - jboss.jca:service=RARDeployment,name='qpid-ra-0.10.rar' + jboss.jca:service=RARDeployment,name='qpid-ra-.rar' javax.jms.Destination - destinationType=TOPIC - destinationAddress=amq.topic + DestinationAddress=amq.topic @@ -138,10 +136,10 @@ can be customized for your environment. Please see the Qpid Java Client document QpidConnectionFactory - jboss.jca:service=RARDeployment,name='qpid-ra-0.10.rar' + jboss.jca:service=RARDeployment,name='qpid-ra-.rar' javax.jms.ConnectionFactory - connectionURL=amqp://anonymous:@client/test?brokerlist='tcp://localhost:5672?sasl_mechs='ANONYMOUS'' + ConnectionURL=amqp://anonymous:@client/test?brokerlist='tcp://localhost:5672?sasl_mechs='PLAIN'' diff --git a/java/jca/build.xml b/java/jca/build.xml index 934514aa52..42a19ff83a 100644 --- a/java/jca/build.xml +++ b/java/jca/build.xml @@ -22,18 +22,26 @@ + + + + + + + + + + + - - - - - + - + @@ -67,6 +75,9 @@ - + + + diff --git a/java/jca/rar/src/main/resources/META-INF/jboss-ra.xml b/java/jca/rar/src/main/resources/META-INF/jboss-ra.xml new file mode 100644 index 0000000000..f459b1efc1 --- /dev/null +++ b/java/jca/rar/src/main/resources/META-INF/jboss-ra.xml @@ -0,0 +1,33 @@ + + + + + TransactionManagerLocatorClass + java.lang.String + org.apache.qpid.ra.tm.JBossTransactionManagerLocator + + + TransactionManagerLocatorMethod + java.lang.String + getTm + + diff --git a/java/jca/rar/src/main/resources/META-INF/ra.xml b/java/jca/rar/src/main/resources/META-INF/ra.xml new file mode 100755 index 0000000000..a9374f52d7 --- /dev/null +++ b/java/jca/rar/src/main/resources/META-INF/ra.xml @@ -0,0 +1,230 @@ + + + + + + QPID Resource Adapter + QPID Resource Adapter + + Apache Software Foundation + JMS 1.1 Server + 1.0 + + + + The ASF licenses this file to you under the Apache License, + Version 2.0 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the + License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + + true + + + + org.apache.qpid.ra.QpidResourceAdapter + + Client ID for the connection + ClientId + java.lang.String + client_id + + + + Number of setup attempts before failing + SetupAttempts + java.lang.Integer + 5 + + + + Interval between setup attempts in milliseconds + SetupInterval + java.lang.Long + 5000 + + + + Use local transactions rather than XA + UseLocalTx + java.lang.Boolean + false + + + + Broker host + Host + java.lang.String + localhost + + + + Broker port + Port + java.lang.Integer + 5672 + + + + Virtual Path for Connection Factory + Path + java.lang.String + test + + + + Connection URL + ConnectionURL + java.lang.String + amqp://anonymous:passwd@client/test?brokerlist='tcp://localhost?sasl_mechs='PLAIN'' + + + + Use a JMS Connection per MessageHandler + UseConnectionPerHandler + java.lang.Boolean + true + + + + + org.apache.qpid.ra.QpidRAManagedConnectionFactory + + + Default session type + SessionDefaultType + java.lang.String + javax.jms.Queue + + + + Specify lock timeout in seconds + UseTryLock + java.lang.Integer + 0 + + + + Use local transactions rather than XA + UseLocalTx + java.lang.Boolean + false + + + + Client ID for the connection + ClientId + java.lang.String + client_id + + + + Connection URL + ConnectionURL + java.lang.String + + + + + Broker host + Host + java.lang.String + localhost + + + + Broker port + Port + java.lang.Integer + 5672 + + + + Virtual Path for Connection Factory + Path + java.lang.String + test + + + org.apache.qpid.ra.QpidRAConnectionFactory + org.apache.qpid.ra.QpidRAConnectionFactoryImpl + javax.jms.Session + org.apache.qpid.ra.QpidRASessionImpl + + XATransaction + + BasicPassword + javax.resource.spi.security.PasswordCredential + + false + + + + + javax.jms.MessageListener + + org.apache.qpid.ra.inflow.QpidActivationSpec + + destination + + + + + + + org.apache.qpid.ra.admin.QpidQueue + org.apache.qpid.ra.admin.QpidQueueImpl + + DestinationAddress + java.lang.String + + + + org.apache.qpid.ra.admin.QpidTopic + org.apache.qpid.ra.admin.QpidTopicImpl + + DestinationAddress + java.lang.String + + + + javax.jms.ConnectionFactory + org.apache.qpid.ra.admin.QpidConnectionFactoryProxy + + ConnectionURL + java.lang.String + + + + diff --git a/java/jca/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxy.java b/java/jca/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxy.java index a948948d6a..d7ca29e04a 100644 --- a/java/jca/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxy.java +++ b/java/jca/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxy.java @@ -27,13 +27,17 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.Serializable; -import javax.jms.ConnectionFactory; import javax.jms.Connection; +import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.naming.NamingException; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; import javax.naming.Reference; import javax.naming.Referenceable; import javax.naming.spi.ObjectFactory; +import javax.jms.TopicConnection; +import javax.jms.TopicConnectionFactory; import org.apache.qpid.client.AMQConnectionFactory; @@ -44,7 +48,7 @@ import org.slf4j.LoggerFactory; * * */ -public class QpidConnectionFactoryProxy implements Externalizable, Referenceable, ConnectionFactory, Serializable +public class QpidConnectionFactoryProxy implements QueueConnectionFactory, TopicConnectionFactory, Externalizable, Referenceable, Serializable { private static final Logger _log = LoggerFactory.getLogger(QpidDestinationProxy.class); @@ -100,13 +104,6 @@ public class QpidConnectionFactoryProxy implements Externalizable, Referenceable try { _delegate = new AMQConnectionFactory(getConnectionURL()); - /* - QpidResourceAdapter ra = new QpidResourceAdapter(); - QpidRAManagedConnectionFactory mcf = new QpidRAManagedConnectionFactory(); - mcf.setResourceAdapter(ra); - mcf.setConnectionURL(getConnectionURL()); - delegate = new QpidRAConnectionFactoryImpl(mcf, null); - */ return ((Referenceable) _delegate).getReference(); } catch(Exception e) @@ -162,7 +159,63 @@ public class QpidConnectionFactoryProxy implements Externalizable, Referenceable */ public Connection createConnection(final String userName, final String password) throws JMSException { - return _delegate.createConnection(userName, password); + try + { + if(_delegate == null) + { + getReference(); + } + + return _delegate.createConnection(userName, password); + } + catch(Exception e) + { + throw new JMSException(e.getMessage()); + } + } + + /** + * Create a queue connection + * @return The queue connection + * @exception JMSException Thrown if the operation fails + */ + public QueueConnection createQueueConnection() throws JMSException + { + return (QueueConnection)createConnection(); + } + + /** + * Create a queue connection + * @param userName The user name + * @param password The password + * @return The connection + * @exception JMSException Thrown if the operation fails + */ + public QueueConnection createQueueConnection(final String userName, final String password) throws JMSException + { + return (QueueConnection)createConnection(userName, password); + } + + /** + * Create a topic connection + * @return The topic connection + * @exception JMSException Thrown if the operation fails + */ + public TopicConnection createTopicConnection() throws JMSException + { + return (TopicConnection)createConnection(); + } + + /** + * Create a topic connection + * @param userName The user name + * @param password The password + * @return The topic connection + * @exception JMSException Thrown if the operation fails + */ + public TopicConnection createTopicConnection(final String userName, final String password) throws JMSException + { + return (TopicConnection)createConnection(userName, password); } } diff --git a/java/jca/src/main/resources/META-INF/jboss-ra.xml b/java/jca/src/main/resources/META-INF/jboss-ra.xml deleted file mode 100644 index f459b1efc1..0000000000 --- a/java/jca/src/main/resources/META-INF/jboss-ra.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - TransactionManagerLocatorClass - java.lang.String - org.apache.qpid.ra.tm.JBossTransactionManagerLocator - - - TransactionManagerLocatorMethod - java.lang.String - getTm - - diff --git a/java/jca/src/main/resources/META-INF/ra.xml b/java/jca/src/main/resources/META-INF/ra.xml deleted file mode 100755 index a9374f52d7..0000000000 --- a/java/jca/src/main/resources/META-INF/ra.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - - - - QPID Resource Adapter - QPID Resource Adapter - - Apache Software Foundation - JMS 1.1 Server - 1.0 - - - - The ASF licenses this file to you under the Apache License, - Version 2.0 (the "License"); you may not use this file except - in compliance with the License. You may obtain a copy of the - License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - - true - - - - org.apache.qpid.ra.QpidResourceAdapter - - Client ID for the connection - ClientId - java.lang.String - client_id - - - - Number of setup attempts before failing - SetupAttempts - java.lang.Integer - 5 - - - - Interval between setup attempts in milliseconds - SetupInterval - java.lang.Long - 5000 - - - - Use local transactions rather than XA - UseLocalTx - java.lang.Boolean - false - - - - Broker host - Host - java.lang.String - localhost - - - - Broker port - Port - java.lang.Integer - 5672 - - - - Virtual Path for Connection Factory - Path - java.lang.String - test - - - - Connection URL - ConnectionURL - java.lang.String - amqp://anonymous:passwd@client/test?brokerlist='tcp://localhost?sasl_mechs='PLAIN'' - - - - Use a JMS Connection per MessageHandler - UseConnectionPerHandler - java.lang.Boolean - true - - - - - org.apache.qpid.ra.QpidRAManagedConnectionFactory - - - Default session type - SessionDefaultType - java.lang.String - javax.jms.Queue - - - - Specify lock timeout in seconds - UseTryLock - java.lang.Integer - 0 - - - - Use local transactions rather than XA - UseLocalTx - java.lang.Boolean - false - - - - Client ID for the connection - ClientId - java.lang.String - client_id - - - - Connection URL - ConnectionURL - java.lang.String - - - - - Broker host - Host - java.lang.String - localhost - - - - Broker port - Port - java.lang.Integer - 5672 - - - - Virtual Path for Connection Factory - Path - java.lang.String - test - - - org.apache.qpid.ra.QpidRAConnectionFactory - org.apache.qpid.ra.QpidRAConnectionFactoryImpl - javax.jms.Session - org.apache.qpid.ra.QpidRASessionImpl - - XATransaction - - BasicPassword - javax.resource.spi.security.PasswordCredential - - false - - - - - javax.jms.MessageListener - - org.apache.qpid.ra.inflow.QpidActivationSpec - - destination - - - - - - - org.apache.qpid.ra.admin.QpidQueue - org.apache.qpid.ra.admin.QpidQueueImpl - - DestinationAddress - java.lang.String - - - - org.apache.qpid.ra.admin.QpidTopic - org.apache.qpid.ra.admin.QpidTopicImpl - - DestinationAddress - java.lang.String - - - - javax.jms.ConnectionFactory - org.apache.qpid.ra.admin.QpidConnectionFactoryProxy - - ConnectionURL - java.lang.String - - - - diff --git a/java/management/common/src/main/java/management-common.bnd b/java/management/common/src/main/java/management-common.bnd index 5a6be6bb15..5ae9791299 100644 --- a/java/management/common/src/main/java/management-common.bnd +++ b/java/management/common/src/main/java/management-common.bnd @@ -17,7 +17,7 @@ # under the License. # -ver: 0.19.0 +ver: 0.21.0 Bundle-SymbolicName: qpid-management-common Bundle-Version: ${ver} diff --git a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ConfigurationManagement.java b/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ConfigurationManagement.java deleted file mode 100644 index 4582dc4088..0000000000 --- a/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ConfigurationManagement.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.management.common.mbeans; - -import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation; - -import javax.management.MBeanOperationInfo; - -public interface ConfigurationManagement -{ - - String TYPE = "ConfigurationManagement"; - - /** - * Reload the - * @throws ConfigurationException - */ - @MBeanOperation(name="reloadSecurityConfiguration", - description = "Force a reload of the security configuration sections", - impact = MBeanOperationInfo.ACTION) - void reloadSecurityConfiguration() throws Exception; - -} diff --git a/java/management/example/src/main/java/org/apache/qpid/example/jmxexample/AddQueue.java b/java/management/example/src/main/java/org/apache/qpid/example/jmxexample/AddQueue.java index b858742c4e..f82408bd27 100644 --- a/java/management/example/src/main/java/org/apache/qpid/example/jmxexample/AddQueue.java +++ b/java/management/example/src/main/java/org/apache/qpid/example/jmxexample/AddQueue.java @@ -36,15 +36,14 @@ import org.apache.qpid.management.common.mbeans.ManagedExchange; public class AddQueue { - public static void main(String[] args) { //Example: add 'newqueue' to the 'test' virtualhost and bind to the 'amq.direct' exchange //TODO: take these parameters as arguments - + addQueue("test", "amq.direct", "newqueue"); } - + private static JMXConnector getJMXConnection() throws Exception { //TODO: Take these parameters as main+method arguments @@ -52,52 +51,55 @@ public class AddQueue int port = 8999; String username = "admin"; String password = "admin"; - + Map env = new HashMap(); JMXServiceURL jmxUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/jmxrmi"); //Add user credential's to environment map for RMIConnector startup. env.put(JMXConnector.CREDENTIALS, new String[] {username,password}); - + return JMXConnectorFactory.connect(jmxUrl, env); } - - public static boolean addQueue(String virHost, String exchName, String queueName) { + public static boolean addQueue(String virHost, String exchName, String queueName) + { JMXConnector jmxc = null; try { jmxc = getJMXConnection(); - + MBeanServerConnection mbsc = jmxc.getMBeanServerConnection(); ObjectName hostManagerObjectName = new ObjectName( "org.apache.qpid:" + "type=VirtualHost.VirtualHostManager," + - "VirtualHost=" + virHost + ",*"); + "VirtualHost=" + ObjectName.quote(virHost) + ",*"); Set vhostManagers = mbsc.queryNames(hostManagerObjectName, null); - + if(vhostManagers.size() == 0) { + System.out.println("VirtualHostManager MBean wasnt found: " + virHost); + //The vhostManager MBean wasnt found, cant procede return false; } - + ManagedBroker vhostManager = (ManagedBroker) MBeanServerInvocationHandler.newProxyInstance( mbsc, (ObjectName) vhostManagers.toArray()[0], ManagedBroker.class, false); ObjectName customExchangeObjectName = new ObjectName( "org.apache.qpid:" + "type=VirtualHost.Exchange," + - "VirtualHost=" + virHost + "," + - "name=" + exchName + "," + - "ExchangeType=direct,*"); + "VirtualHost=" + ObjectName.quote(virHost) + "," + + "name=" + ObjectName.quote(exchName) + ",*"); Set exchanges = mbsc.queryNames(customExchangeObjectName, null); - + if(exchanges.size() == 0) { + System.out.println("Exchange wasnt found: " + exchName); + //The exchange doesnt exist, cant procede. return false; } @@ -105,12 +107,14 @@ public class AddQueue //create the MBean proxy ManagedExchange managedExchange = (ManagedExchange) MBeanServerInvocationHandler.newProxyInstance( mbsc, (ObjectName) exchanges.toArray()[0], ManagedExchange.class, false); - + try { //create the new durable queue and bind it. vhostManager.createNewQueue(queueName, null, true); + System.out.println("Created queue: " + queueName); managedExchange.createNewBinding(queueName,queueName); + System.out.println("Bound queue to exchange: "+ exchName); } catch (Exception e) { @@ -126,7 +130,7 @@ public class AddQueue { System.out.println("Could not add queue due to error :" + e.getMessage()); e.printStackTrace(); - } + } finally { if(jmxc != null) @@ -141,9 +145,8 @@ public class AddQueue } } } - + return false; - } } diff --git a/java/module.xml b/java/module.xml index af77d84e86..9146403d04 100644 --- a/java/module.xml +++ b/java/module.xml @@ -48,16 +48,19 @@ - + - - - + + + + + + @@ -74,6 +77,7 @@ + @@ -84,7 +88,10 @@ + + + @@ -94,15 +101,6 @@ - - - - - - - - - @@ -160,30 +158,57 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + - - - + + + + + + + + + + - @@ -197,14 +222,21 @@ - + - + + + + + + + + @@ -212,7 +244,7 @@ - + @@ -229,7 +261,7 @@ - + @@ -239,9 +271,7 @@ - - - + @@ -255,6 +285,29 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -280,6 +333,13 @@ + + + + + + + - - - + + @@ -335,14 +394,13 @@ - - + @@ -350,16 +408,14 @@ + - - - @@ -383,7 +439,7 @@ - + @@ -447,35 +503,54 @@ - + - + - + - + + + + + + + - + - + + + + + + + + + + + + + + - + - + @@ -494,14 +569,7 @@ - - - - - - - @@ -688,8 +756,7 @@ - + @@ -697,10 +764,10 @@ - - + + - + @@ -713,8 +780,8 @@ + destdir="${module.coverage}" + datafile="${cobertura.datafile}"> @@ -750,7 +817,8 @@ qpid.name=${project.name} --> - + + @@ -763,7 +831,7 @@ qpid.name=${project.name} deprecation="${javac.deprecation}" srcdir="${project.root}/broker/src/velocity/java" > - + @@ -793,7 +861,7 @@ qpid.name=${project.name} - + @@ -810,7 +878,7 @@ qpid.name=${project.name} - + diff --git a/java/perftests/build.xml b/java/perftests/build.xml index c59986c06d..d29649ad68 100644 --- a/java/perftests/build.xml +++ b/java/perftests/build.xml @@ -33,7 +33,7 @@ - + diff --git a/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef b/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef new file mode 100644 index 0000000000..7559b5934e --- /dev/null +++ b/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef @@ -0,0 +1,37 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Impact of Message Size Bytes/S +chartSubtitle=Transient messages +chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes. + +xAxisTitle=Message Size (B) +yAxisTitle=Throughput (KB/s) + +series.1.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All' +series.1.legend=Current +series.1.dir=${csvCurrentDir} +series.1.colourName=red + +series.2.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All' +series.2.legend=Baseline +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1001-MessageSize-Transient.chartdef b/java/perftests/etc/chartdefs/1001-MessageSize-Transient.chartdef deleted file mode 100644 index 757a396dff..0000000000 --- a/java/perftests/etc/chartdefs/1001-MessageSize-Transient.chartdef +++ /dev/null @@ -1,32 +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. -# - -chartType=XYLINE -chartTitle=Impact of Message Size -chartSubtitle=Transient messages -xAxisTitle=Message Size (B) -yAxisTitle=Throughput (KB/s) - -series.1.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All' -series.1.legend=Current -series.1.dir=${csvCurrentDir} - -series.2.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All' -series.2.legend=Baseline -series.2.dir=${csvBaselineDir} diff --git a/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef new file mode 100644 index 0000000000..db8a5f3896 --- /dev/null +++ b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef @@ -0,0 +1,37 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Impact of Message Size Bytes/S +chartSubtitle=Persistent messages +chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes. + +xAxisTitle=Message Size (B) +yAxisTitle=Throughput (KB/s) + +series.1.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '% PERSISTENT' AND participantName = 'All' +series.1.legend=Current +series.1.dir=${csvCurrentDir} +series.1.colourName=red + +series.2.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '% PERSISTENT' AND participantName = 'All' +series.2.legend=Baseline +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1002-MessageSize-Persistent.chartdef b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent.chartdef deleted file mode 100644 index 58c280e227..0000000000 --- a/java/perftests/etc/chartdefs/1002-MessageSize-Persistent.chartdef +++ /dev/null @@ -1,32 +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. -# - -chartType=XYLINE -chartTitle=Impact of Message Size -chartSubtitle=Persistent messages -xAxisTitle=Message Size (B) -yAxisTitle=Throughput (KB/s) - -series.1.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '% PERSISTENT' AND participantName = 'All' -series.1.legend=Current -series.1.dir=${csvCurrentDir} - -series.2.statement=SELECT payloadSizeB, throughputKbPerS FROM MessageSize WHERE testName like '% PERSISTENT' AND participantName = 'All' -series.2.legend=Baseline -series.2.dir=${csvBaselineDir} diff --git a/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef b/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef new file mode 100644 index 0000000000..7f18fcc986 --- /dev/null +++ b/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef @@ -0,0 +1,37 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Impact of Message Size +chartSubtitle=Transient messages +chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes. + +xAxisTitle=Message Size (B) +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT payloadSizeB, throughputMessagesPerS FROM MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All' +series.1.legend=Current +series.1.dir=${csvCurrentDir} +series.1.colourName=red + +series.2.statement=SELECT payloadSizeB, throughputMessagesPerS FROM MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All' +series.2.legend=Baseline +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef b/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef new file mode 100644 index 0000000000..667be044bc --- /dev/null +++ b/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef @@ -0,0 +1,37 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Impact of Message Size +chartSubtitle=Persistent messages +chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes. + +xAxisTitle=Message Size (B) +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT payloadSizeB, throughputMessagesPerS FROM MessageSize WHERE testName like '% PERSISTENT' AND participantName = 'All' +series.1.legend=Current +series.1.dir=${csvCurrentDir} +series.2.colourName=red + +series.2.statement=SELECT payloadSizeB, throughputMessagesPerS FROM MessageSize WHERE testName like '% PERSISTENT' AND participantName = 'All' +series.2.legend=Baseline +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef new file mode 100644 index 0000000000..b3038c1671 --- /dev/null +++ b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef @@ -0,0 +1,47 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Varying number of producers - auto ack +chartSubtitle=Persistent 1KB messages +chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB. + +xAxisTitle=Producers +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '1' and acknowledgeMode = '1' +series.1.legend=1 Consumer +series.1.dir=${csvCurrentDir} +series.1.colourName=red + +series.2.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '5' and acknowledgeMode = '1' +series.2.legend=5 Consumer +series.2.dir=${csvCurrentDir} +series.2.colourName=blue + +series.3.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '10' and acknowledgeMode = '1' +series.3.legend=10 Consumer +series.3.dir=${csvCurrentDir} +series.3.colourName=green + +series.4.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '1' and acknowledgeMode = '1' +series.4.legend=1 Consumer (baseline) +series.4.dir=${csvBaselineDir} +series.4.colourName=dark_red +series.4.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers.chartdef b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers.chartdef deleted file mode 100644 index f39e7c3d0d..0000000000 --- a/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers.chartdef +++ /dev/null @@ -1,40 +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. -# - -chartType=XYLINE -chartTitle=Varying number of producers -chartSubtitle=Persistent 1KB messages -xAxisTitle=Producers -yAxisTitle=Throughput (KB/s) - -series.1.statement=SELECT totalNumberOfProducers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '1' -series.1.legend=1 Consumer -series.1.dir=${csvCurrentDir} - -series.2.statement=SELECT totalNumberOfProducers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '5' -series.2.legend=5 Consumer -series.2.dir=${csvCurrentDir} - -series.3.statement=SELECT totalNumberOfProducers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '10' -series.3.legend=10 Consumer -series.3.dir=${csvCurrentDir} - -series.4.statement=SELECT totalNumberOfProducers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '1' -series.4.legend=1 Consumer (baseline) -series.4.dir=${csvBaselineDir} diff --git a/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef new file mode 100644 index 0000000000..d1f3d6e9a4 --- /dev/null +++ b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef @@ -0,0 +1,47 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Varying number of consumers - auto ack +chartSubtitle=Persistent 1KB messages +chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB. + +xAxisTitle=Consumers +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '1' and acknowledgeMode = '1' +series.1.legend=1 Producer +series.1.dir=${csvCurrentDir} +series.1.colourName=blue + +series.2.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '5' and acknowledgeMode = '1' +series.2.legend=5 Producers +series.2.dir=${csvCurrentDir} +series.2.colourName=green + +series.3.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10' and acknowledgeMode = '1' +series.3.legend=10 Producers +series.3.dir=${csvCurrentDir} +series.3.colourName=red + +series.4.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10' and acknowledgeMode = '1' +series.4.legend=10 Producers (baseline) +series.4.dir=${csvBaselineDir} +series.4.colourName=dark_red +series.4.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers.chartdef b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers.chartdef deleted file mode 100644 index 0f0b35a7c8..0000000000 --- a/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers.chartdef +++ /dev/null @@ -1,40 +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. -# - -chartType=XYLINE -chartTitle=Varying number of consumers -chartSubtitle=Persistent 1KB messages -xAxisTitle=Consumers -yAxisTitle=Throughput (KB/s) - -series.1.statement=SELECT totalNumberOfConsumers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '1' -series.1.legend=1 Producer -series.1.dir=${csvCurrentDir} - -series.2.statement=SELECT totalNumberOfConsumers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '5' -series.2.legend=5 Producers -series.2.dir=${csvCurrentDir} - -series.3.statement=SELECT totalNumberOfConsumers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10' -series.3.legend=10 Producers -series.3.dir=${csvCurrentDir} - -series.4.statement=SELECT totalNumberOfConsumers, throughputKbPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10' -series.4.legend=10 Producers (baseline) -series.4.dir=${csvBaselineDir} diff --git a/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef b/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef new file mode 100644 index 0000000000..42ba6f8f20 --- /dev/null +++ b/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef @@ -0,0 +1,47 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Varying number of producers - transacted +chartSubtitle=Persistent 1KB messages +chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB. + +xAxisTitle=Producers +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '1' and acknowledgeMode = '0' +series.1.legend=1 Consumer +series.1.dir=${csvCurrentDir} +series.1.colourName=red + +series.2.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '5' and acknowledgeMode = '0' +series.2.legend=5 Consumer +series.2.dir=${csvCurrentDir} +series.2.colourName=blue + +series.3.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '10' and acknowledgeMode = '0' +series.3.legend=10 Consumer +series.3.dir=${csvCurrentDir} +series.3.colourName=green + +series.4.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfConsumers = '1' and acknowledgeMode = '0' +series.4.legend=1 Consumer (baseline) +series.4.dir=${csvBaselineDir} +series.4.colourName=dark_red +series.4.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef b/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef new file mode 100644 index 0000000000..0afd162ad0 --- /dev/null +++ b/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef @@ -0,0 +1,47 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Varying number of consumers - transacted +chartSubtitle=Persistent 1KB messages +chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB. + +xAxisTitle=Consumers +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '1' and acknowledgeMode = '0' +series.1.legend=1 Producer +series.1.dir=${csvCurrentDir} +series.1.colourName=blue + +series.2.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '5' and acknowledgeMode = '0' +series.2.legend=5 Producers +series.2.dir=${csvCurrentDir} +series.2.colourName=green + +series.3.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10' and acknowledgeMode = '0' +series.3.legend=10 Producers +series.3.dir=${csvCurrentDir} +series.3.colourName=red + +series.4.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '10' and acknowledgeMode = '0' +series.4.legend=10 Producers (baseline) +series.4.dir=${csvBaselineDir} +series.4.colourName=dark_red +series.4.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef index 30aee40c27..827f8b5567 100644 --- a/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef +++ b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef @@ -19,17 +19,20 @@ chartType=BAR chartTitle=Performance of acknowledgement modes -chartSubtitle=Persistent messages (1024b) +chartSubtitle=Persistent messages (1KB) +chartDescription=1P 1C, persistent, with message payload 1KB. + xAxisTitle=Acknowledge mode (0=session transacted; 1=auto-acknowledge) -yAxisTitle=Throughput (KB/s) +yAxisTitle=Throughput (messages/s) -series.1.statement=SELECT acknowledgeMode, throughputKbPerS FROM AcknowledgementModes WHERE testName like 'Persistent%' AND participantName = 'All' ORDER BY acknowledgeMode +series.1.statement=SELECT acknowledgeMode, throughputMessagesPerS FROM AcknowledgementModes WHERE testName like 'Persistent%' AND participantName = 'All' ORDER BY acknowledgeMode series.1.legend=Current series.1.dir=${csvCurrentDir} +series.1.colourName=blue - -series.2.statement=SELECT acknowledgeMode, throughputKbPerS FROM AcknowledgementModes WHERE testName like 'Persistent%' AND participantName = 'All' ORDER BY acknowledgeMode +series.2.statement=SELECT acknowledgeMode, throughputMessagesPerS FROM AcknowledgementModes WHERE testName like 'Persistent%' AND participantName = 'All' ORDER BY acknowledgeMode series.2.legend=Baseline series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red diff --git a/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef index 7a26391deb..8ca5d838e2 100644 --- a/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef +++ b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef @@ -20,13 +20,17 @@ chartType=BAR chartTitle=Performance of acknowledgement modes chartSubtitle=Transient messages (1024b) +chartDescription=1P 1C, transient, with message payload 1KB. + xAxisTitle=Acknowledge mode (0=session transacted; 1=auto-acknowledge) -yAxisTitle=Throughput (KB/s) +yAxisTitle=Throughput (messages/s) -series.1.statement=SELECT acknowledgeMode, throughputKbPerS FROM AcknowledgementModes WHERE testName like 'Transient%' AND participantName = 'All' ORDER BY acknowledgeMode +series.1.statement=SELECT acknowledgeMode, throughputMessagesPerS FROM AcknowledgementModes WHERE testName like 'Transient%' AND participantName = 'All' ORDER BY acknowledgeMode series.1.legend=Current series.1.dir=${csvCurrentDir} +series.1.colourName=blue -series.2.statement=SELECT acknowledgeMode, throughputKbPerS FROM AcknowledgementModes WHERE testName like 'Transient%' AND participantName = 'All' ORDER BY acknowledgeMode +series.2.statement=SELECT acknowledgeMode, throughputMessagesPerS FROM AcknowledgementModes WHERE testName like 'Transient%' AND participantName = 'All' ORDER BY acknowledgeMode series.2.legend=Baseline series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red diff --git a/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef b/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef new file mode 100644 index 0000000000..97b712e027 --- /dev/null +++ b/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef @@ -0,0 +1,37 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# 'License'); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Transaction Batch Sizes Equal +chartSubtitle=Persistent 1KB messages +chartDescription=1P 1C, persistent, transacted with message payload 1KB with producer/consumer batch size varying between 1-400 messages for both P and C + +xAxisTitle=Batch Size +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT batchSize, throughputMessagesPerS FROM BatchSize WHERE participantName = 'All' +series.1.legend=Equal Producer/Consumer +series.1.dir=${csvCurrentDir} +series.1.colourName=red + +series.2.statement=SELECT batchSize, throughputMessagesPerS FROM BatchSize WHERE participantName = 'All' +series.2.legend=Equal Producer/Consumer (Baseline) +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1030-BatchSize.chartdef b/java/perftests/etc/chartdefs/1030-BatchSize.chartdef deleted file mode 100644 index 1f01aa85aa..0000000000 --- a/java/perftests/etc/chartdefs/1030-BatchSize.chartdef +++ /dev/null @@ -1,33 +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. -# - -chartType=XYLINE -chartTitle=Transaction Batch Size -chartSubtitle=Persistent 1KB messages -xAxisTitle=Batch Size -yAxisTitle=Throughput (KB/s) - -series.1.statement=SELECT batchSize, throughputKbPerS FROM BatchSize WHERE participantName = 'All' -series.1.legend=Current -series.1.dir=${csvCurrentDir} - -series.2.statement=SELECT batchSize, throughputKbPerS FROM BatchSize WHERE participantName = 'All' -series.2.legend=Baseline -series.2.dir=${csvBaselineDir} - diff --git a/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef b/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef new file mode 100644 index 0000000000..51b3bb2144 --- /dev/null +++ b/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef @@ -0,0 +1,53 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# 'License'); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Transaction Batch Size Unequal +chartSubtitle=Persistent 1KB messages +chartDescription=1P 1C, persistent, transacted with message payload 1KB with fixed batch size 1 for one party whilst other varies between 1-400 messages + +xAxisTitle=Batch Size +yAxisTitle=Throughput (messages/s) + +# +# If csvjdbc could do sub-selects (allowing us to extract the consumer/producer batch size from the All Consumers/All Producers rows), +# we would not need the workaround where we have testdef place the consumer/producer batch size into testName field +# + +series.1.statement=SELECT testName, throughputMessagesPerS FROM BatchSizeProducerVaries WHERE participantName = 'All' +series.1.legend=Variable Producer, Fixed Consumer +series.1.dir=${csvCurrentDir} +series.1.colourName=red + +series.2.statement=SELECT testName, throughputMessagesPerS FROM BatchSizeProducerVaries WHERE participantName = 'All' +series.2.legend=Variable Producer, Fixed Consumer (Baseline) +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.strokeWidth=-1 + +series.3.statement=SELECT testName, throughputMessagesPerS FROM BatchSizeConsumerVaries WHERE participantName = 'All' +series.3.legend=Fixed Producer, Variable Consumer +series.3.dir=${csvCurrentDir} +series.3.colourName=blue + +series.4.statement=SELECT testName, throughputMessagesPerS FROM BatchSizeConsumerVaries WHERE participantName = 'All' +series.4.legend=Fixed Producer, Variable Consumer (Baseline) +series.4.dir=${csvBaselineDir} +series.4.colourName=dark_blue +series.4.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef index 42ed69c19d..aacedab421 100644 --- a/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef +++ b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef @@ -20,13 +20,17 @@ chartType=BAR chartTitle=Queue Types chartSubtitle=Persistent 1KB messages +chartDescription=1P 1C, persistent, auto-ack with message payload 1KB. Sorted queue - 160,000 random keys, Priority - iteriates priority 0..9. + xAxisTitle=Queue Types -yAxisTitle=Throughput (KB/s) +yAxisTitle=Throughput (messages/s) -series.1.statement=SELECT testName, throughputKbPerS FROM QueueTypes WHERE participantName = 'All' +series.1.statement=SELECT testName, throughputMessagesPerS FROM QueueTypes WHERE participantName = 'All' series.1.legend=Current series.1.dir=${csvCurrentDir} +series.1.colourName=blue -series.2.statement=SELECT testName, throughputKbPerS FROM QueueTypes WHERE participantName = 'All' +series.2.statement=SELECT testName, throughputMessagesPerS FROM QueueTypes WHERE participantName = 'All' series.2.legend=Baseline series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red diff --git a/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef b/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef new file mode 100644 index 0000000000..46696bf942 --- /dev/null +++ b/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef @@ -0,0 +1,49 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Varying number of producer sessions on single connection +chartSubtitle=Persistent messages (1024b) +chartDescription=1-80P transacted on single connection, 20C transacted on separate connections, persistent, message payload 1KB. + +xAxisTitle=Number of producer sessions +yAxisTitle=Throughput (KB/s) + +# testName contains the number of sessions +series.1.statement=SELECT testName, throughputKbPerS FROM VaryingNumberOfProducerSessionsSingleConnection WHERE participantName = 'All' +series.1.legend=Current - End-to-end throughput +series.1.dir=${csvCurrentDir} +series.1.colourName=red + +series.2.statement=SELECT testName, throughputKbPerS FROM VaryingNumberOfProducerSessionsSingleConnection WHERE participantName = 'All Producers' +series.2.legend=Current - Producer only throughput +series.2.dir=${csvCurrentDir} +series.2.colourName=blue + +series.3.statement=SELECT testName, throughputKbPerS FROM VaryingNumberOfProducerSessionsSingleConnection WHERE participantName = 'All' +series.3.legend=Baseline - End-to-end throughput +series.3.dir=${csvBaselineDir} +series.3.colourName=dark_red +series.3.strokeWidth=-1 + +series.4.statement=SELECT testName, throughputKbPerS FROM VaryingNumberOfProducerSessionsSingleConnection WHERE participantName = 'All Producers' +series.4.legend=Baseline - Producer only throughput +series.4.dir=${csvBaselineDir} +series.4.colourName=dark_blue +series.4.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef new file mode 100644 index 0000000000..5081b379e7 --- /dev/null +++ b/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef @@ -0,0 +1,37 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Impact of non-overlapping selectors on queue consumers with transient messages +chartSubtitle=Transient 1KB messages +xAxisTitle=Consumers +yAxisTitle=Throughput (messages/s) +chartDescription=Impact of non-overlapping selectors on queue consumers with transient messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32. + +series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - NON_PERSISTENT%' +series.1.legend=Current +series.1.dir=${csvCurrentDir} +series.1.colourName=blue + +series.2.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - NON_PERSISTENT%' +series.2.legend=Baseline +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.stokeWidth=-1 + diff --git a/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef new file mode 100644 index 0000000000..137f7bde36 --- /dev/null +++ b/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef @@ -0,0 +1,43 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Impact of non-overlapping selectors on queue consumers with persistent messages +chartSubtitle=Persistent 1KB messages +xAxisTitle=Consumers +yAxisTitle=Throughput (messages/s) +chartDescription=Impact of non-overlapping selectors on queue consumers with persistent messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32.. + + +series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - PERSISTENT' +series.1.legend=Current +series.1.dir=${csvCurrentDir} +series.1.colourName=blue + +series.2.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - PERSISTENT' +series.2.legend=Baseline +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.stokeWidth=-1 + +series.3.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '1' and acknowledgeMode = '1' +series.3.legend=Current: no selectors +series.3.dir=${csvCurrentDir} +series.3.colourName=green + diff --git a/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef new file mode 100644 index 0000000000..74f370317b --- /dev/null +++ b/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef @@ -0,0 +1,36 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Impact of 50%-overlapping selectors in queue consumers with transient messages +chartSubtitle=Transient 1KB messages +xAxisTitle=Consumers +yAxisTitle=Throughput (messages/s) +chartDescription=Impact of 50%-overlapping selectors in queue consumers with transient messages, auto-ack, message payload 1KB, 1 producer, varying number of consumers from 2 to 32. + +series.1.statement=SELECT totalNumberOfConsumers,throughputMessagesPerS FROM QueueConsumersWithOverlappingSelectors WHERE participantName = 'All' and testName like '%50_ overlapping - NON_PERSISTENT%' +series.1.legend=Current +series.1.dir=${csvCurrentDir} +series.1.colourName=blue + +series.2.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithOverlappingSelectors WHERE participantName = 'All' and testName like '%50_ overlapping - NON_PERSISTENT%' +series.2.legend=Baseline +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.stokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef new file mode 100644 index 0000000000..0dd78e02ef --- /dev/null +++ b/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef @@ -0,0 +1,42 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=XYLINE +chartTitle=Impact of 50%-overlapping selectors in queue consumers with persistent messages +chartDescription=Impact of 50%-overlapping selectors in queue consumers with persistent messages, auto-ack, message payload of 1KB, 1 producer, varying number of consumers from 2 to 32. +chartSubtitle=Persistent 1KB messages +xAxisTitle=Consumers +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithOverlappingSelectors WHERE participantName = 'All' and testName like '%50_ overlapping - PERSISTENT%' +series.1.legend=Current +series.1.dir=${csvCurrentDir} +series.1.colourName=blue + +series.2.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithOverlappingSelectors WHERE participantName = 'All' and testName like '%50_ overlapping - PERSISTENT%' +series.2.legend=Baseline +series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.stokeWidth=-1 + +series.3.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM VaryingNumberOfParticipants WHERE participantName = 'All' and totalNumberOfProducers = '1' and acknowledgeMode = '1' +series.3.legend=Current: no selectors +series.3.dir=${csvCurrentDir} +series.3.colourName=green + diff --git a/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef index 305c5009e2..073cee810d 100644 --- a/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef +++ b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef @@ -20,13 +20,18 @@ chartType=XYLINE chartTitle=Number of topic consumers chartSubtitle=Transient 1KB messages +chartDescription=1P 1-100C transient, transacted, with message payload 1KB. + xAxisTitle=Numer of consumers -yAxisTitle=Throughput (KB/s) +yAxisTitle=Throughput (messages/s) -series.1.statement=SELECT testName, throughputKbPerS FROM Topic-NumberOfConsumers WHERE participantName = 'All' +series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM Topic-NumberOfConsumers WHERE participantName = 'All' series.1.legend=Current series.1.dir=${csvCurrentDir} +series.1.colourName=red -series.2.statement=SELECT testName, throughputKbPerS FROM Topic-NumberOfConsumers WHERE participantName = 'All' +series.2.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM Topic-NumberOfConsumers WHERE participantName = 'All' series.2.legend=Baseline series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef index 9bc53e5a9e..b32f43d0c2 100644 --- a/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef +++ b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef @@ -20,13 +20,18 @@ chartType=XYLINE chartTitle=Number of topics chartSubtitle=Transient 1KB messages +chartDescription=1,10,50,100 PC, transient, transacted, with each PC pair having own topic, message payload 1KB. + xAxisTitle=Numer of topics -yAxisTitle=Throughput (KB/s) +yAxisTitle=Throughput (messages/s) -series.1.statement=SELECT testName, throughputKbPerS FROM Topic-NumberOfTopics WHERE participantName = 'All' +series.1.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM Topic-NumberOfTopics WHERE participantName = 'All' series.1.legend=Current series.1.dir=${csvCurrentDir} +series.1.colourName=red -series.2.statement=SELECT testName, throughputKbPerS FROM Topic-NumberOfTopics WHERE participantName = 'All' +series.2.statement=SELECT totalNumberOfProducers, throughputMessagesPerS FROM Topic-NumberOfTopics WHERE participantName = 'All' series.2.legend=Baseline series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.strokeWidth=-1 diff --git a/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef index ce64d14ac4..5fd905ab4f 100644 --- a/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef +++ b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef @@ -20,13 +20,18 @@ chartType=BAR chartTitle=Topic transient/durable subscriptions chartSubtitle=1KB messages -xAxisTitle=Durable subscription -yAxisTitle=Throughput (KB/s) +chartDescription=1P 10C, transacted, message payload 1KB, transient messages on non-durable sub, persistent messages on durable sub -series.1.statement=SELECT isDurableSubscription, throughputKbPerS FROM Topic-Persistence WHERE participantName = 'All Consumers' +xAxisTitle=Subscription type (true durable, false non durable) +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT isDurableSubscription, throughputMessagesPerS FROM Topic-Persistence WHERE participantName = 'All Consumers' series.1.legend=Current series.1.dir=${csvCurrentDir} +series.1.colourName=blue -series.2.statement=SELECT isDurableSubscription, throughputKbPerS FROM Topic-Persistence WHERE participantName = 'All Consumers' +series.2.statement=SELECT isDurableSubscription, throughputMessagesPerS FROM Topic-Persistence WHERE participantName = 'All Consumers' series.2.legend=Baseline series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.stokeWidth=2 diff --git a/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef index 5ccc166fc8..9edb1950a4 100644 --- a/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef +++ b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef @@ -20,13 +20,18 @@ chartType=BAR chartTitle=Topic acknowledge modes chartSubtitle=Transient 1KB messages -xAxisTitle=Ack Mode -yAxisTitle=Throughput (KB/s) +chartDescription=1P 10C, transient, non-durable subscription, message payload 1KB -series.1.statement=SELECT acknowledgeMode, throughputKbPerS FROM Topic-AckModes WHERE participantName = 'All' +xAxisTitle=Ack Mode (0=transaction 1=auto-ack) +yAxisTitle=Throughput (messages/s) + +series.1.statement=SELECT acknowledgeMode, throughputMessagesPerS FROM Topic-AckModes WHERE participantName = 'All' series.1.legend=Current series.1.dir=${csvCurrentDir} +series.1.colourName=blue -series.2.statement=SELECT acknowledgeMode, throughputKbPerS FROM Topic-AckModes WHERE participantName = 'All' +series.2.statement=SELECT acknowledgeMode, throughputMessagesPerS FROM Topic-AckModes WHERE participantName = 'All' series.2.legend=Baseline series.2.dir=${csvBaselineDir} +series.2.colourName=dark_red +series.2.stokeWidth=2 diff --git a/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef index c892ea16cf..67a0278bff 100644 --- a/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef +++ b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef @@ -20,21 +20,27 @@ chartType=STATISTICAL_BAR chartTitle=Impact of message size on latency chartSubtitle=Transient messages +chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes. + xAxisTitle=Message Size (B) yAxisTitle=Latency (millis) series.1.statement=SELECT payloadSizeB, maxLatency, 0 FROM Latency-MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All Consumers' series.1.legend=Maximum latency series.1.dir=${csvCurrentDir} +series.1.colourName=blue series.2.statement=SELECT payloadSizeB, averageLatency,latencyStandardDeviation FROM Latency-MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All Consumers' series.2.legend=Average latency series.2.dir=${csvCurrentDir} +series.2.colourName=red series.3.statement=SELECT payloadSizeB, averageLatency,latencyStandardDeviation FROM Latency-MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All Consumers' series.3.legend=Average latency (baseline) series.3.dir=${csvBaselineDir} +series.3.colourName=dark_red series.4.statement=SELECT payloadSizeB, minLatency,0 FROM Latency-MessageSize WHERE testName like '%TRANSIENT' AND participantName = 'All Consumers' series.4.legend=Minimum latency series.4.dir=${csvCurrentDir} +series.4.colourName=green diff --git a/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef index 167e62603a..e9761f07d8 100644 --- a/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef +++ b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef @@ -20,21 +20,27 @@ chartType=STATISTICAL_BAR chartTitle=Impact of message size on latency chartSubtitle=Persistent messages +chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes. + xAxisTitle=Message Size (B) yAxisTitle=Latency (millis) series.1.statement=SELECT payloadSizeB, maxLatency, 0 FROM Latency-MessageSize WHERE testName like '%PERSISTENT' AND participantName = 'All Consumers' series.1.legend=Maximum latency series.1.dir=${csvCurrentDir} +series.1.colourName=blue series.2.statement=SELECT payloadSizeB, averageLatency, latencyStandardDeviation FROM Latency-MessageSize WHERE testName like '%PERSISTENT' AND participantName = 'All Consumers' series.2.legend=Average latency series.2.dir=${csvCurrentDir} +series.2.colourName=red series.3.statement=SELECT payloadSizeB, averageLatency, latencyStandardDeviation FROM Latency-MessageSize WHERE testName like '%PERSISTENT' AND participantName = 'All Consumers' series.3.legend=Average latency (baseline) series.3.dir=${csvBaselineDir} +series.3.colourName=dark_red series.4.statement=SELECT payloadSizeB, minLatency, 0 FROM Latency-MessageSize WHERE testName like '%PERSISTENT' AND participantName = 'All Consumers' series.4.legend=Minimum latency series.4.dir=${csvCurrentDir} +series.4.colourName=green diff --git a/java/perftests/etc/chartdefs/2011-Latency-QueuesWithNonOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/2011-Latency-QueuesWithNonOverlappingSelectors-Transient.chartdef index 45c6031b1e..663912b622 100644 --- a/java/perftests/etc/chartdefs/2011-Latency-QueuesWithNonOverlappingSelectors-Transient.chartdef +++ b/java/perftests/etc/chartdefs/2011-Latency-QueuesWithNonOverlappingSelectors-Transient.chartdef @@ -20,21 +20,27 @@ chartType=STATISTICAL_BAR chartTitle=Latency with consumers having non-overlapping selectors chartSubtitle=Transient 1KB messages +chartDescription=1P 1-10C, transient, auto-ack, with message payload 1KB. + xAxisTitle=Consumers yAxisTitle=Latency (millis) series.1.statement=SELECT totalNumberOfConsumers, maxLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - NON_PERSISTENT%' series.1.legend=Max latency series.1.dir=${csvCurrentDir} +series.1.colourName=blue series.2.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - NON_PERSISTENT%' series.2.legend=Average latency series.2.dir=${csvCurrentDir} +series.2.colourName=red series.3.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - NON_PERSISTENT%' series.3.legend=Average latency (baseline) series.3.dir=${csvBaselineDir} +series.3.colourName=dark_red series.4.statement=SELECT totalNumberOfConsumers, minLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - NON_PERSISTENT%' series.4.legend=Min latency series.4.dir=${csvCurrentDir} +series.4.colourName=green diff --git a/java/perftests/etc/chartdefs/2012-Latency-QueuesWithOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/2012-Latency-QueuesWithOverlappingSelectors-Transient.chartdef index 351a4639b1..3b9e207e10 100644 --- a/java/perftests/etc/chartdefs/2012-Latency-QueuesWithOverlappingSelectors-Transient.chartdef +++ b/java/perftests/etc/chartdefs/2012-Latency-QueuesWithOverlappingSelectors-Transient.chartdef @@ -20,21 +20,27 @@ chartType=STATISTICAL_BAR chartTitle=Latency with consumers having 50%-overlapping selectors chartSubtitle=Transient 1KB messages +chartDescription=1P 1-10C, transient, auto-ack, with message payload 1KB. + xAxisTitle=Consumers yAxisTitle=Latency (millis) series.1.statement=SELECT totalNumberOfConsumers, maxLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - NON_PERSISTENT%' series.1.legend=Max latency series.1.dir=${csvCurrentDir} +series.1.colourName=blue series.2.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - NON_PERSISTENT%' series.2.legend=Average latency series.2.dir=${csvCurrentDir} +series.2.colourName=red series.3.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - NON_PERSISTENT%' series.3.legend=Average latency (baseline) series.3.dir=${csvBaselineDir} +series.3.colourName=dark_red series.4.statement=SELECT totalNumberOfConsumers, minLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - NON_PERSISTENT%' series.4.legend=Min latency series.4.dir=${csvCurrentDir} +series.4.colourName=green diff --git a/java/perftests/etc/chartdefs/2021-Latency-QueuesWithNonOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/2021-Latency-QueuesWithNonOverlappingSelectors-Persistent.chartdef index 9d95075b3d..296d115d3f 100644 --- a/java/perftests/etc/chartdefs/2021-Latency-QueuesWithNonOverlappingSelectors-Persistent.chartdef +++ b/java/perftests/etc/chartdefs/2021-Latency-QueuesWithNonOverlappingSelectors-Persistent.chartdef @@ -20,21 +20,27 @@ chartType=STATISTICAL_BAR chartTitle=Latency with consumers having non-overlapping selectors chartSubtitle=Persistent 1KB messages +chartDescription=1P 1-10C, persistent, auto-ack, with message payload 1KB. + xAxisTitle=Consumers yAxisTitle=Latency (millis) series.1.statement=SELECT totalNumberOfConsumers, maxLatency,0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - PERSISTENT' series.1.legend=Max latency series.1.dir=${csvCurrentDir} +series.1.colourName=blue series.2.statement=SELECT totalNumberOfConsumers, averageLatency, latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - PERSISTENT' series.2.legend=Average latency series.2.dir=${csvCurrentDir} +series.2.colourName=red series.3.statement=SELECT totalNumberOfConsumers, averageLatency, latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - PERSISTENT' series.3.legend=Average latency (baseline) series.3.dir=${csvBaselineDir} +series.3.colourName=dark_red series.4.statement=SELECT totalNumberOfConsumers, minLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%non overlapping - PERSISTENT' series.4.legend=Min latency series.4.dir=${csvCurrentDir} +series.4.colourName=green diff --git a/java/perftests/etc/chartdefs/2022-Latency-QueuesWithOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/2022-Latency-QueuesWithOverlappingSelectors-Persistent.chartdef index 9a323d4044..65be60b5e5 100644 --- a/java/perftests/etc/chartdefs/2022-Latency-QueuesWithOverlappingSelectors-Persistent.chartdef +++ b/java/perftests/etc/chartdefs/2022-Latency-QueuesWithOverlappingSelectors-Persistent.chartdef @@ -20,21 +20,27 @@ chartType=STATISTICAL_BAR chartTitle=Latency with consumers having 50%-overlapping selectors chartSubtitle=Persistent 1KB messages +chartDescription=1P 1-10C, persistent, auto-ack, with message payload 1KB. + xAxisTitle=Consumers yAxisTitle=Latency (millis) series.1.statement=SELECT totalNumberOfConsumers, maxLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - PERSISTENT%' series.1.legend=Max latency series.1.dir=${csvCurrentDir} +series.1.colourName=blue series.2.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - PERSISTENT%' series.2.legend=Average latency series.2.dir=${csvCurrentDir} +series.2.colourName=red series.3.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - PERSISTENT%' series.3.legend=Average latency (baseline) series.3.dir=${csvBaselineDir} +series.3.colourName=dark_red series.4.statement=SELECT totalNumberOfConsumers, minLatency, 0 FROM Latency-QueuesWithSelectors WHERE participantName = 'All Consumers' and testName like '%overlapping 50% - PERSISTENT%' series.4.legend=Min latency series.4.dir=${csvCurrentDir} +series.4.colourName=green diff --git a/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef index 82cf1168ef..d52b05d870 100644 --- a/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef +++ b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef @@ -20,25 +20,32 @@ chartType=STATISTICAL_BAR chartTitle=Latency, varying number of participants chartSubtitle=Persistent 1KB messages +chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB. + xAxisTitle=Consumers yAxisTitle=Latency (millis) series.1.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 1 producer - PERSISTENT' series.1.legend=1 producer series.1.dir=${csvCurrentDir} +series.1.colourName=blue series.2.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 2 producers - PERSISTENT' series.2.legend=2 producers series.2.dir=${csvCurrentDir} +series.2.colourName=green series.3.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 5 producers - PERSISTENT' series.3.legend=5 producers series.3.dir=${csvCurrentDir} +series.3.colourName=magenta series.4.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 10 producers - PERSISTENT' series.4.legend=10 producers series.4.dir=${csvCurrentDir} +series.4.colourName=red series.5.statement=SELECT totalNumberOfConsumers, averageLatency,latencyStandardDeviation FROM Latency-VaryingNumberOfParticipants WHERE participantName = 'All Consumers' and testName like '% - 10 producers - PERSISTENT' series.5.legend=10 producers (baseline) series.5.dir=${csvBaselineDir} +series.5.colourName=dark_red diff --git a/java/perftests/etc/chartdefs/2041-Latency-QueueTypes.chartdef b/java/perftests/etc/chartdefs/2041-Latency-QueueTypes.chartdef index c1aae19376..dac8a52f89 100644 --- a/java/perftests/etc/chartdefs/2041-Latency-QueueTypes.chartdef +++ b/java/perftests/etc/chartdefs/2041-Latency-QueueTypes.chartdef @@ -20,21 +20,27 @@ chartType=STATISTICAL_BAR chartTitle=Latency on different queues chartSubtitle=Persistent 1KB messages +chartDescription=1P 1C, persistent, auto-ack with message payload 1KB. Sorted queue - 400 varied keys, Priority - 200 varied priorities. + xAxisTitle=Queue type yAxisTitle=Latency (millis) series.1.statement=SELECT testName, maxLatency,0 FROM Latency-QueueTypes WHERE participantName = 'All Consumers' series.1.legend=Maximum latency series.1.dir=${csvCurrentDir} +series.1.colourName=blue series.2.statement=SELECT testName, averageLatency,latencyStandardDeviation FROM Latency-QueueTypes WHERE participantName = 'All Consumers' series.2.legend=Average Latency series.2.dir=${csvCurrentDir} +series.2.colourName=red series.3.statement=SELECT testName, averageLatency,latencyStandardDeviation FROM Latency-QueueTypes WHERE participantName = 'All Consumers' series.3.legend=Average Latency (baseline) series.3.dir=${csvBaselineDir} +series.3.colourName=dark_red series.4.statement=SELECT testName, minLatency,0 FROM Latency-QueueTypes WHERE participantName = 'All Consumers' series.4.legend=Minimum latency series.4.dir=${csvCurrentDir} +series.4.colourName=green diff --git a/java/perftests/etc/chartdefs/timeseries/1001-Large-Messages-Transient.chartdef b/java/perftests/etc/chartdefs/timeseries/1001-Large-Messages-Transient.chartdef new file mode 100644 index 0000000000..e77f7b4eff --- /dev/null +++ b/java/perftests/etc/chartdefs/timeseries/1001-Large-Messages-Transient.chartdef @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=TIMELINE +chartTitle=Large transient messages +chartDescription=1P 1C, transient, auto-ack, with message payload 65536 bytes. + +xAxisTitle=Date +yAxisTitle=Throughput (KB/s) + +series.1.statement=SELECT insertedTimestamp, throughputKbPerS FROM RESULTS WHERE participantName = 'All' AND testName = 'Message Size - 1P-1C - TRANSIENT' and payloadSizeB = 65536 +series.1.colourName=red +series.1.legend=Throughput diff --git a/java/perftests/etc/chartdefs/timeseries/1002-Large-Messages-Persistent.chartdef b/java/perftests/etc/chartdefs/timeseries/1002-Large-Messages-Persistent.chartdef new file mode 100644 index 0000000000..ffcf8c26b8 --- /dev/null +++ b/java/perftests/etc/chartdefs/timeseries/1002-Large-Messages-Persistent.chartdef @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=TIMELINE +chartTitle=Large persistent messages +chartDescription=1P 1C, persistent, auto-ack, with message payload 65536 bytes. + +xAxisTitle=Date +yAxisTitle=Throughput (KB/s) + +series.1.statement=SELECT insertedTimestamp, throughputKbPerS FROM RESULTS WHERE participantName = 'All' AND testName = 'Message Size - 1P-1C - PERSISTENT' and payloadSizeB = 65536 +series.1.colourName=red +series.1.legend=Throughput diff --git a/java/perftests/etc/chartdefs/timeseries/1011-MultipleProducersAndConsumers-Persistent.chartdef b/java/perftests/etc/chartdefs/timeseries/1011-MultipleProducersAndConsumers-Persistent.chartdef new file mode 100644 index 0000000000..ba01d4b7ad --- /dev/null +++ b/java/perftests/etc/chartdefs/timeseries/1011-MultipleProducersAndConsumers-Persistent.chartdef @@ -0,0 +1,30 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=TIMELINE +chartTitle=Multiple producers and consumers - auto ack +chartSubtitle=Persistent 1KB messages +chartDescription=10 P/Cs, persistent, auto-ack, with message payload 1KB. + +xAxisTitle=Date +yAxisTitle=Throughput (KB/s) + +series.1.statement=SELECT insertedTimestamp, throughputKbPerS FROM RESULTS WHERE participantName = 'All' AND testName = 'Varying number of participants: 10 consumers - 10 producers - PERSISTENT' +series.1.colourName=red +series.1.legend=Throughput \ No newline at end of file diff --git a/java/perftests/etc/chartdefs/timeseries/1030-Batch-Size-Small.chartdef b/java/perftests/etc/chartdefs/timeseries/1030-Batch-Size-Small.chartdef new file mode 100644 index 0000000000..f755bf4a5b --- /dev/null +++ b/java/perftests/etc/chartdefs/timeseries/1030-Batch-Size-Small.chartdef @@ -0,0 +1,30 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=TIMELINE +chartTitle=Transactions +chartSubtitle=Persistent 1KB messages +chartDescription=1P 1C, persistent, transacted with message payload 1KB with batch size 1 for both P and C + +xAxisTitle=Date +yAxisTitle=Throughput (KB/s) + +series.1.statement=SELECT insertedTimestamp, throughputKbPerS FROM RESULTS WHERE participantName = 'All' AND testName = 'Batch Size 1-1 - PERSISTENT' +series.1.colourName=red +series.1.legend=Throughput \ No newline at end of file diff --git a/java/perftests/etc/chartdefs/timeseries/1031-Batch-Size-Large.chartdef b/java/perftests/etc/chartdefs/timeseries/1031-Batch-Size-Large.chartdef new file mode 100644 index 0000000000..ca390f8226 --- /dev/null +++ b/java/perftests/etc/chartdefs/timeseries/1031-Batch-Size-Large.chartdef @@ -0,0 +1,30 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=TIMELINE +chartTitle=Transactions with large batches +chartSubtitle=Persistent 1KB messages +chartDescription=1P 1C, persistent, transacted with message payload 1KB with batch size 100 for both P and C + +xAxisTitle=Date +yAxisTitle=Throughput (KB/s) + +series.1.statement=SELECT insertedTimestamp, throughputKbPerS FROM RESULTS WHERE participantName = 'All' AND testName = 'Batch Size 100-100 - PERSISTENT' +series.1.colourName=red +series.1.legend=Throughput diff --git a/java/perftests/etc/chartdefs/timeseries/1040-SortedQueue.chartdef b/java/perftests/etc/chartdefs/timeseries/1040-SortedQueue.chartdef new file mode 100644 index 0000000000..6dce3a1a77 --- /dev/null +++ b/java/perftests/etc/chartdefs/timeseries/1040-SortedQueue.chartdef @@ -0,0 +1,30 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +chartType=TIMELINE +chartTitle=Sorted queue +chartSubtitle=Persistent 1KB messages +chartDescription=1P 1C, persistent, auto-ack with message payload 1KB. Sorted queue with 160,000 random keys + +xAxisTitle=Date +yAxisTitle=Throughput (KB/s) + +series.1.statement=SELECT insertedTimestamp, throughputKbPerS FROM RESULTS WHERE participantName = 'All' AND testName = 'queue-type:sorted-queue' +series.1.colourName=red +series.1.legend=Throughput \ No newline at end of file diff --git a/java/perftests/etc/perftests-jndi.properties b/java/perftests/etc/perftests-jndi.properties index f33af6fdd5..ce6493b49a 100644 --- a/java/perftests/etc/perftests-jndi.properties +++ b/java/perftests/etc/perftests-jndi.properties @@ -20,3 +20,7 @@ java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextF connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672' destination.controllerqueue = direct://amq.direct//controllerqueue?autodelete='true' + +jdbcDriverClass=org.apache.derby.jdbc.EmbeddedDriver +# writes to a results database in ./perftestResultsDb by default. +jdbcUrl=jdbc:derby:perftestResultsDb;create=true diff --git a/java/perftests/etc/run-perftests.sh b/java/perftests/etc/run-perftests.sh new file mode 100755 index 0000000000..f963879e7e --- /dev/null +++ b/java/perftests/etc/run-perftests.sh @@ -0,0 +1,37 @@ +#!/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. +# + +# Runs the perftests using a typical configuration. + +BASE_DIR=`dirname $0` +DURATION=${1:-5000} +AMQP_VERSION=${2:-0-91} + +echo Will run perftests using a maximum duration of ${DURATION}ms and AMQP protocol version ${AMQP_VERSION}. +echo + +java -cp "${BASE_DIR}:${BASE_DIR}/../../build/lib/*" \ + -Dqpid.amqp.version=${AMQP_VERSION} -Dqpid.dest_syntax=BURL \ + -Dqpid.disttest.duration=$DURATION \ + org.apache.qpid.disttest.ControllerRunner \ + jndi-config=${BASE_DIR}/perftests-jndi.properties \ + test-config=${BASE_DIR}/testdefs \ + distributed=false \ + writeToDb=true diff --git a/java/perftests/etc/testdefs/BatchSize.js b/java/perftests/etc/testdefs/BatchSize.js new file mode 100644 index 0000000000..f17751b7b5 --- /dev/null +++ b/java/perftests/etc/testdefs/BatchSize.js @@ -0,0 +1,102 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +var jsonObject = { + _tests:[] +}; + +var duration = 30000; + +var txBatchSizes = [[1,1], [2,2], [5,5], [10,10], [20,20], [50,50], [100,100], [200,200], [400,400]]; + +var acknowledgeMode = 0; +var deliveryMode = 2; +var messageSize = 1024; + +for(i=0; i < txBatchSizes.length ; i++) +{ + var producerBatchSize = txBatchSizes[i][0]; + var consumerBatchSize = txBatchSizes[i][1]; + var queueName = "txBatchSize" + producerBatchSize + "_" + consumerBatchSize; + var destination = "direct://amq.direct//" + queueName + "?durable='true'"; + + var test = { + "_name": "Batch Size " + producerBatchSize + "-" + consumerBatchSize + " - PERSISTENT", + "_queues":[ + { + "_name": queueName, + "_durable": true + } + ], + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_acknowledgeMode": acknowledgeMode, + "_producers": [ + { + "_name": "Producer1", + "_destinationName": destination, + "_messageSize": messageSize, + "_deliveryMode": deliveryMode, + "_batchSize": producerBatchSize, + "_maximumDuration": duration + } + ] + } + ] + } + ] + }, + { + "_name": "consumingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_acknowledgeMode": acknowledgeMode, + "_consumers": [ + { + "_name": "Consumer1", + "_destinationName": destination, + "_batchSize": consumerBatchSize, + "_maximumDuration": duration + } + ] + } + ] + } + ] + } + ] + }; + + jsonObject._tests= jsonObject._tests.concat(test); +} diff --git a/java/perftests/etc/testdefs/BatchSize.json b/java/perftests/etc/testdefs/BatchSize.json deleted file mode 100644 index eeb446bad6..0000000000 --- a/java/perftests/etc/testdefs/BatchSize.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "_tests":[ - { - "_name": "Batch Size- PERSISTENT"; - "_iterations":[ - { - "_batchSize": 1 - }, - { - "_batchSize": 2 - }, - { - "_batchSize": 5 - }, - { - "_batchSize": 10 - }, - { - "_batchSize": 20 - }, - { - "_batchSize": 50 - }, - { - "_batchSize": 100 - } - ], - "_queues":[ - { - "_name": "direct://amq.direct//batchSize?durable='true'", - "_durable": true - } - ], - "_clients":[ - { - "_name": "producingClient", - "_connections":[ - { - "_name": "connection1", - "_factory": "connectionfactory", - "_sessions": [ - { - "_sessionName": "session1", - "_acknowledgeMode": 0, - "_producers": [ - { - "_name": "Producer1", - "_destinationName": "direct://amq.direct//batchSize?durable='true'", - "_messageSize": 1024, - "_maximumDuration": 30000, - "_deliveryMode": 2 - } - ] - } - ] - } - ] - }, - { - "_name": "consumingClient", - "_connections":[ - { - "_name": "connection1", - "_factory": "connectionfactory", - "_sessions": [ - { - "_sessionName": "session1", - "_acknowledgeMode": 0, - "_consumers": [ - { - "_name": "Consumer1", - "_destinationName": "direct://amq.direct//batchSize?durable='true'", - "_maximumDuration": 30000 - } - ] - } - ] - } - ] - } - ] - } - ] -} diff --git a/java/perftests/etc/testdefs/BatchSizeConsumerVaries.js b/java/perftests/etc/testdefs/BatchSizeConsumerVaries.js new file mode 100644 index 0000000000..b491f431c9 --- /dev/null +++ b/java/perftests/etc/testdefs/BatchSizeConsumerVaries.js @@ -0,0 +1,102 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +var jsonObject = { + _tests:[] +}; + +var duration = 30000; + +var txBatchSizes = [[1,1], [1,2], [1,5], [1,10], [1,20], [1,50], [1,100], [1,200], [1,400]]; + +var acknowledgeMode = 0; +var deliveryMode = 2; +var messageSize = 1024; + +for(i=0; i < txBatchSizes.length ; i++) +{ + var producerBatchSize = txBatchSizes[i][0]; + var consumerBatchSize = txBatchSizes[i][1]; + var queueName = "txBatchSize" + producerBatchSize + "_" + consumerBatchSize; + var destination = "direct://amq.direct//" + queueName + "?durable='true'"; + + var test = { + "_name": consumerBatchSize,// hack - use test name to expose the consumer batch size on the All result rows + "_queues":[ + { + "_name": queueName, + "_durable": true + } + ], + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_acknowledgeMode": acknowledgeMode, + "_producers": [ + { + "_name": "Producer1", + "_destinationName": destination, + "_messageSize": messageSize, + "_deliveryMode": deliveryMode, + "_batchSize": producerBatchSize, + "_maximumDuration": duration + } + ] + } + ] + } + ] + }, + { + "_name": "consumingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_acknowledgeMode": acknowledgeMode, + "_consumers": [ + { + "_name": "Consumer1", + "_destinationName": destination, + "_batchSize": consumerBatchSize, + "_maximumDuration": duration + } + ] + } + ] + } + ] + } + ] + }; + + jsonObject._tests= jsonObject._tests.concat(test); +} diff --git a/java/perftests/etc/testdefs/BatchSizeProducerVaries.js b/java/perftests/etc/testdefs/BatchSizeProducerVaries.js new file mode 100644 index 0000000000..ac23c52c9e --- /dev/null +++ b/java/perftests/etc/testdefs/BatchSizeProducerVaries.js @@ -0,0 +1,102 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +var jsonObject = { + _tests:[] +}; + +var duration = 30000; + +var txBatchSizes = [[1,1], [2,1], [5,1], [10,1], [20,1], [50,1], [100,1], [200,1], [400,1]]; + +var acknowledgeMode = 0; +var deliveryMode = 2; +var messageSize = 1024; + +for(i=0; i < txBatchSizes.length ; i++) +{ + var producerBatchSize = txBatchSizes[i][0]; + var consumerBatchSize = txBatchSizes[i][1]; + var queueName = "txBatchSize" + producerBatchSize + "_" + consumerBatchSize; + var destination = "direct://amq.direct//" + queueName + "?durable='true'"; + + var test = { + "_name": producerBatchSize,// hack - use test name to expose the producer batch size on the All result rows + "_queues":[ + { + "_name": queueName, + "_durable": true + } + ], + "_clients":[ + { + "_name": "producingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_acknowledgeMode": acknowledgeMode, + "_producers": [ + { + "_name": "Producer1", + "_destinationName": destination, + "_messageSize": messageSize, + "_deliveryMode": deliveryMode, + "_batchSize": producerBatchSize, + "_maximumDuration": duration + } + ] + } + ] + } + ] + }, + { + "_name": "consumingClient", + "_connections":[ + { + "_name": "connection1", + "_factory": "connectionfactory", + "_sessions": [ + { + "_sessionName": "session1", + "_acknowledgeMode": acknowledgeMode, + "_consumers": [ + { + "_name": "Consumer1", + "_destinationName": destination, + "_batchSize": consumerBatchSize, + "_maximumDuration": duration + } + ] + } + ] + } + ] + } + ] + }; + + jsonObject._tests= jsonObject._tests.concat(test); +} diff --git a/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js b/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js new file mode 100644 index 0000000000..0dd45b0392 --- /dev/null +++ b/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js @@ -0,0 +1,120 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +var jsonObject = { + _tests:[] +}; + +for (var i=0; i<2; i++) +{ + var deliveryMode = i+1; + var durable = (deliveryMode == 2); + var suffix = durable ? "PERSISTENT" : "NON-PERSISTENT"; + var queueName = "direct://amq.direct//queue-selectors-" + suffix + "?durable='" + durable + "'"; + var consumerNumbers = [1, 2, 4, 8, 16, 32]; + var consumerAcknowledgeMode = 1; + for (var j=0; j - + diff --git a/java/perftests/example/perftests-jndi.properties b/java/perftests/example/perftests-jndi.properties index 04a8ad9101..1c0fd57663 100644 --- a/java/perftests/example/perftests-jndi.properties +++ b/java/perftests/example/perftests-jndi.properties @@ -24,3 +24,6 @@ java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextF connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:5672' destination.controllerqueue = direct://amq.direct//controllerqueue?autodelete='true' + +driverName=org.apache.derby.jdbc.EmbeddedDriver +jdbcUrl=jdbc:derby:/tmp/perftestResultsDb;create=true diff --git a/java/perftests/example/run.sh b/java/perftests/example/run.sh index cb68c52853..31124a060a 100755 --- a/java/perftests/example/run.sh +++ b/java/perftests/example/run.sh @@ -18,5 +18,5 @@ # under the License. # -java -cp ".:${QPID_HOME}/lib/*" -Dqpid.dest_syntax=BURL org.apache.qpid.disttest.ControllerRunner jndi-config=perftests-jndi.properties test-config=$1 distributed=false +java -cp ".:${QPID_HOME}/lib/*" -Dqpid.dest_syntax=BURL org.apache.qpid.disttest.ControllerRunner jndi-config=perftests-jndi.properties test-config=$1 distributed=false writeToDb=true diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java index 8c1f8675e3..e962bfe799 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ArgumentParser.java @@ -34,10 +34,14 @@ public class ArgumentParser throw new IllegalArgumentException("arguments must have format =: " + arg); } - if(initialValues.put(splitArg[0], splitArg[1]) == null) + + String argumentKey = splitArg[0]; + String argumentValue = splitArg[1]; + if(!initialValues.containsKey(argumentKey)) { throw new IllegalArgumentException("not a valid configuration property: " + arg); } + initialValues.put(argumentKey, argumentValue); } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ConfigFileHelper.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ConfigFileHelper.java index fb4c1b700b..ee374e180d 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/ConfigFileHelper.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ConfigFileHelper.java @@ -60,15 +60,4 @@ public class ConfigFileHelper return testConfigFile; } - - /** - * generateOutputCsvNameFrom("/config/testConfigFile.js", "/output") returns /output/testConfigFile.csv - */ - public String generateOutputCsvNameFrom(String testConfigFile, String outputDir) - { - final String filenameOnlyWithExtension = new File(testConfigFile).getName(); - final String cvsFile = filenameOnlyWithExtension.replaceFirst(".?\\w*$", ".csv"); - - return new File(outputDir, cvsFile).getAbsolutePath(); - } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java index aea0ea301a..449130a328 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ControllerRunner.java @@ -19,9 +19,9 @@ */ package org.apache.qpid.disttest; +import java.io.File; import java.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.IOException; +import java.util.ArrayList; import java.util.List; import javax.naming.Context; @@ -30,9 +30,9 @@ import org.apache.qpid.disttest.controller.Controller; import org.apache.qpid.disttest.controller.ResultsForAllTests; import org.apache.qpid.disttest.controller.config.Config; import org.apache.qpid.disttest.controller.config.ConfigReader; +import org.apache.qpid.disttest.db.ResultsDbWriter; import org.apache.qpid.disttest.jms.ControllerJmsDelegate; import org.apache.qpid.disttest.results.aggregation.Aggregator; -import org.apache.qpid.disttest.results.formatting.CSVFormater; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,20 +43,29 @@ public class ControllerRunner extends AbstractRunner public static final String TEST_CONFIG_PROP = "test-config"; public static final String DISTRIBUTED_PROP = "distributed"; public static final String OUTPUT_DIR_PROP = "outputdir"; + public static final String WRITE_TO_DB = "writeToDb"; + public static final String RUN_ID = "runId"; private static final String TEST_CONFIG_DEFAULT = "perftests-config.json"; private static final String DISTRIBUTED_DEFAULT = "false"; private static final String OUTPUT_DIR_DEFAULT = "."; + public static final String WRITE_TO_DB_DEFAULT = "false"; private final Aggregator _aggregator = new Aggregator(); private final ConfigFileHelper _configFileHelper = new ConfigFileHelper(); + private ResultsFileWriter _resultsFileWriter; + + private ResultsDbWriter _resultsDbWriter; + public ControllerRunner() { getCliOptions().put(TEST_CONFIG_PROP, TEST_CONFIG_DEFAULT); getCliOptions().put(DISTRIBUTED_PROP, DISTRIBUTED_DEFAULT); getCliOptions().put(OUTPUT_DIR_PROP, OUTPUT_DIR_DEFAULT); + getCliOptions().put(WRITE_TO_DB, WRITE_TO_DB_DEFAULT); + getCliOptions().put(RUN_ID, null); } public static void main(String[] args) throws Exception @@ -69,6 +78,8 @@ public class ControllerRunner extends AbstractRunner public void runController() throws Exception { Context context = getContext(); + setUpResultFilesWriter(); + setUpResultsDbWriter(); ControllerJmsDelegate jmsDelegate = new ControllerJmsDelegate(context); @@ -82,6 +93,24 @@ public class ControllerRunner extends AbstractRunner } } + private void setUpResultsDbWriter() + { + String writeToDbStr = getCliOptions().get(WRITE_TO_DB); + if(Boolean.valueOf(writeToDbStr)) + { + String runId = getCliOptions().get(RUN_ID); + _resultsDbWriter = new ResultsDbWriter(getContext(), runId); + _resultsDbWriter.createResultsTableIfNecessary(); + } + } + + void setUpResultFilesWriter() + { + String outputDirString = getCliOptions().get(ControllerRunner.OUTPUT_DIR_PROP); + File outputDir = new File(outputDirString); + _resultsFileWriter = new ResultsFileWriter(outputDir); + } + private void runTests(ControllerJmsDelegate jmsDelegate) { Controller controller = new Controller(jmsDelegate, DistributedTestConstants.REGISTRATION_TIMEOUT, DistributedTestConstants.COMMAND_RESPONSE_TIMEOUT); @@ -92,6 +121,8 @@ public class ControllerRunner extends AbstractRunner try { + List results = new ArrayList(); + for (String testConfigFile : testConfigFiles) { final Config testConfig = buildTestConfigFrom(testConfigFile); @@ -100,8 +131,11 @@ public class ControllerRunner extends AbstractRunner controller.awaitClientRegistrations(); LOGGER.info("Running test : " + testConfigFile); - runTest(controller, testConfigFile); + ResultsForAllTests testResult = runTest(controller, testConfigFile); + results.add(testResult); } + + _resultsFileWriter.writeResultsSummary(results); } catch(Exception e) { @@ -113,7 +147,7 @@ public class ControllerRunner extends AbstractRunner } } - private void runTest(Controller controller, String testConfigFile) + private ResultsForAllTests runTest(Controller controller, String testConfigFile) { final Config testConfig = buildTestConfigFrom(testConfigFile); controller.setConfig(testConfig); @@ -121,9 +155,13 @@ public class ControllerRunner extends AbstractRunner ResultsForAllTests rawResultsForAllTests = controller.runAllTests(); ResultsForAllTests resultsForAllTests = _aggregator.aggregateResults(rawResultsForAllTests); - String outputDir = getCliOptions().get(ControllerRunner.OUTPUT_DIR_PROP); - final String outputFile = _configFileHelper.generateOutputCsvNameFrom(testConfigFile, outputDir); - writeResultsToFile(resultsForAllTests, outputFile); + _resultsFileWriter.writeResultsToFile(resultsForAllTests, testConfigFile); + if(_resultsDbWriter != null) + { + _resultsDbWriter.writeResults(resultsForAllTests); + } + + return resultsForAllTests; } private void createClientsIfNotDistributed(final List testConfigFiles) @@ -148,36 +186,6 @@ public class ControllerRunner extends AbstractRunner } } - private void writeResultsToFile(ResultsForAllTests resultsForAllTests, String outputFile) - { - FileWriter writer = null; - try - { - final String outputCsv = new CSVFormater().format(resultsForAllTests); - writer = new FileWriter(outputFile); - writer.write(outputCsv); - LOGGER.info("Wrote " + resultsForAllTests.getTestResults().size() + " test result(s) to output file " + outputFile); - } - catch (IOException e) - { - throw new DistributedTestException("Unable to write output file " + outputFile, e); - } - finally - { - if (writer != null) - { - try - { - writer.close(); - } - catch (IOException e) - { - LOGGER.error("Failed to close stream for file " + outputFile, e); - } - } - } - } - private Config buildTestConfigFrom(String testConfigFile) { ConfigReader configReader = new ConfigReader(); diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/ResultsFileWriter.java b/java/perftests/src/main/java/org/apache/qpid/disttest/ResultsFileWriter.java new file mode 100644 index 0000000000..81b717403d --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/ResultsFileWriter.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.List; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.results.aggregation.TestResultAggregator; +import org.apache.qpid.disttest.results.formatting.CSVFormatter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ResultsFileWriter +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ResultsFileWriter.class); + + static final String TEST_SUMMARY_FILE_NAME = "test-summary.csv"; + + private final File _outputDir; + + private CSVFormatter _csvFormater = new CSVFormatter(); + + private TestResultAggregator _testResultAggregator = new TestResultAggregator(); + + public ResultsFileWriter(File outputDir) + { + _outputDir = outputDir; + } + + public void writeResultsToFile(ResultsForAllTests resultsForAllTests, String testConfigFile) + { + final String outputFile = generateOutputCsvNameFrom(testConfigFile); + writeResultsToOutputFile(resultsForAllTests, outputFile); + } + + public void writeResultsSummary(List allResultsList) + { + ResultsForAllTests combinedResults = _testResultAggregator.aggregateTestResults(allResultsList); + writeResultsToOutputFile(combinedResults, new File(_outputDir, TEST_SUMMARY_FILE_NAME).getAbsolutePath()); + } + + /** + * generateOutputCsvNameFrom("/config/testConfigFile.js", "/output") returns /output/testConfigFile.csv + */ + private String generateOutputCsvNameFrom(String testConfigFile) + { + final String filenameOnlyWithExtension = new File(testConfigFile).getName(); + final String cvsFile = filenameOnlyWithExtension.replaceFirst(".?\\w*$", ".csv"); + + return new File(_outputDir, cvsFile).getAbsolutePath(); + } + + private void writeResultsToOutputFile(ResultsForAllTests resultsForAllTests, String outputFile) + { + FileWriter writer = null; + try + { + final String outputCsv = _csvFormater.format(resultsForAllTests); + writer = new FileWriter(outputFile); + writer.write(outputCsv); + LOGGER.info("Wrote " + resultsForAllTests.getTestResults().size() + " test result(s) to output file " + outputFile); + } + catch (IOException e) + { + throw new DistributedTestException("Unable to write output file " + outputFile, e); + } + finally + { + if (writer != null) + { + try + { + writer.close(); + } + catch (IOException e) + { + LOGGER.error("Failed to close stream for file " + outputFile, e); + } + } + } + } + + void setCsvFormater(CSVFormatter csvFormater) + { + _csvFormater = csvFormater; + } + + void setTestResultAggregator(TestResultAggregator testResultAggregator) + { + _testResultAggregator = testResultAggregator; + } + +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java index f9d50e8e64..d3a5e30191 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ConsumerParticipant.java @@ -35,7 +35,6 @@ import javax.jms.MessageListener; import org.apache.qpid.disttest.DistributedTestException; import org.apache.qpid.disttest.jms.ClientJmsDelegate; -import org.apache.qpid.disttest.message.ConsumerParticipantResult; import org.apache.qpid.disttest.message.CreateConsumerCommand; import org.apache.qpid.disttest.message.ParticipantResult; import org.slf4j.Logger; @@ -103,16 +102,22 @@ public class ConsumerParticipant implements Participant } Date end = new Date(); - int numberOfMessagesSent = _totalNumberOfMessagesReceived.get(); + int numberOfMessagesReceived = _totalNumberOfMessagesReceived.get(); long totalPayloadSize = _totalPayloadSizeOfAllMessagesReceived.get(); int payloadSize = getPayloadSizeForResultIfConstantOrZeroOtherwise(_allConsumedPayloadSizes); - ConsumerParticipantResult result = _resultFactory.createForConsumer( + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Consumer {} finished consuming. Number of messages consumed: {}", + getName(), numberOfMessagesReceived); + } + + ParticipantResult result = _resultFactory.createForConsumer( getName(), registeredClientName, _command, acknowledgeMode, - numberOfMessagesSent, + numberOfMessagesReceived, payloadSize, totalPayloadSize, start, end, _messageLatencies); @@ -174,7 +179,7 @@ public class ConsumerParticipant implements Participant { LOGGER.trace("Committing: batch size " + _command.getBatchSize() ); } - _jmsDelegate.commitOrAcknowledgeMessage(message, _command.getSessionName()); + _jmsDelegate.commitOrAcknowledgeMessageIfNecessary(_command.getSessionName(), message); } } @@ -199,7 +204,7 @@ public class ConsumerParticipant implements Participant } // commit/acknowledge remaining messages if necessary - _jmsDelegate.commitOrAcknowledgeMessage(message, _command.getSessionName()); + _jmsDelegate.commitOrAcknowledgeMessageIfNecessary(_command.getSessionName(), message); } return false; } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java index bb9ce26f7e..10f62708a4 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ParticipantExecutor.java @@ -108,8 +108,16 @@ public class ParticipantExecutor } finally { + try + { + _participant.releaseResources(); + } + catch(Exception e) + { + LOGGER.error("Participant " + _participant + " unable to release resources", e); + } + _client.sendResults(result); - _participant.releaseResources(); } } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java index 63cbe98b5c..a9da837dea 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/client/ProducerParticipant.java @@ -58,17 +58,25 @@ public class ProducerParticipant implements Participant @Override public ParticipantResult doIt(String registeredClientName) throws Exception { - if (_command.getMaximumDuration() == 0 && _command.getNumberOfMessages() == 0) + long numberOfMessages = _command.getNumberOfMessages(); + long maximumDuration = _command.getMaximumDuration(); + + if (maximumDuration == 0 && numberOfMessages == 0) { throw new DistributedTestException("number of messages and duration cannot both be zero"); } - int acknowledgeMode = _jmsDelegate.getAcknowledgeMode(_command.getSessionName()); + long duration = maximumDuration - _command.getStartDelay(); + if (maximumDuration > 0 && duration <= 0) + { + throw new DistributedTestException("Start delay must be less than maximum test duration"); + } + final long requiredDuration = duration > 0 ? duration : 0; doSleepForStartDelay(); - final long requiredDuration = _command.getMaximumDuration() - _command.getStartDelay(); - + final int batchSize = _command.getBatchSize(); + final int acknowledgeMode = _jmsDelegate.getAcknowledgeMode(_command.getSessionName()); final long startTime = System.currentTimeMillis(); Message lastPublishedMessage = null; @@ -78,10 +86,20 @@ public class ProducerParticipant implements Participant _limiter = ExecutorWithLimitsFactory.createExecutorWithLimit(startTime, requiredDuration); - LOGGER.info("Producer {} about to send messages", getName()); + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Producer {} about to send messages. Duration limit: {} ms, Message limit: {}", + new Object[]{getName(), requiredDuration, numberOfMessages}); + } while (true) { + if (numberOfMessages > 0 && numberOfMessagesSent >= numberOfMessages + || requiredDuration > 0 && System.currentTimeMillis() - startTime >= requiredDuration) + { + break; + } + try { lastPublishedMessage = _limiter.execute(new Callable() @@ -110,35 +128,35 @@ public class ProducerParticipant implements Participant LOGGER.trace("message " + numberOfMessagesSent + " sent by " + this); } - final boolean batchLimitReached = _command.getBatchSize() <= 0 - || numberOfMessagesSent % _command.getBatchSize() == 0; + final boolean batchLimitReached = batchSize <= 0 + || numberOfMessagesSent % batchSize == 0; if (batchLimitReached) { - if (LOGGER.isTraceEnabled() && _command.getBatchSize() > 0) + if (LOGGER.isTraceEnabled() && batchSize > 0) { - LOGGER.trace("Committing: batch size " + _command.getBatchSize() ); + LOGGER.trace("Committing: batch size " + batchSize ); } - _jmsDelegate.commitOrAcknowledgeMessage(lastPublishedMessage, _command.getSessionName()); + _jmsDelegate.commitIfNecessary(_command.getSessionName()); doSleepForInterval(); } - - if (_command.getNumberOfMessages() > 0 && numberOfMessagesSent >= _command.getNumberOfMessages() - || requiredDuration > 0 && System.currentTimeMillis() - startTime >= requiredDuration) - { - break; - } } // commit the remaining batch messages - if (_command.getBatchSize() > 0 && numberOfMessagesSent % _command.getBatchSize() != 0) + if (batchSize > 0 && numberOfMessagesSent % batchSize != 0) { if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Committing: batch size " + _command.getBatchSize() ); + LOGGER.trace("Committing: batch size " + batchSize ); } - _jmsDelegate.commitOrAcknowledgeMessage(lastPublishedMessage, _command.getSessionName()); + _jmsDelegate.commitIfNecessary(_command.getSessionName()); + } + + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Producer {} finished publishing. Number of messages published: {}", + getName(), numberOfMessagesSent); } Date start = new Date(startTime); diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ClientRegistry.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ClientRegistry.java index eaccb54f0e..5a726c50b4 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ClientRegistry.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ClientRegistry.java @@ -57,34 +57,54 @@ public class ClientRegistry return Collections.unmodifiableSet(_registeredClientNames); } - public int awaitClients(int numberOfClientsToAwait, long timeout) + /** + * @return the number of clients that are still absent. + */ + public int awaitClients(final int numberOfClientsToAwait, final long idleTimeout) { - final long endTime = System.currentTimeMillis() + timeout; + long deadlineForNextRegistration = deadline(idleTimeout); - int numberOfClientsAbsent = numberOfClientsToAwait - _registeredClientNames.size(); - long remainingTimeout = endTime - System.currentTimeMillis(); + int numberOfClientsAbsent = numberAbsent(numberOfClientsToAwait); - while(numberOfClientsAbsent > 0 && remainingTimeout > 0) + while(numberOfClientsAbsent > 0 && System.currentTimeMillis() < deadlineForNextRegistration) { synchronized (_lock) { try { - _lock.wait(remainingTimeout); + _lock.wait(idleTimeout); } catch (InterruptedException e) { Thread.currentThread().interrupt(); + return numberOfClientsAbsent; } } - numberOfClientsAbsent = numberOfClientsToAwait - _registeredClientNames.size(); - remainingTimeout = endTime - System.currentTimeMillis(); + int newNumberAbsent = numberAbsent(numberOfClientsToAwait); + if(newNumberAbsent < numberOfClientsAbsent) + { + // a registration was received since the last loop, so reset the timeout + deadlineForNextRegistration = deadline(idleTimeout); + } + + numberOfClientsAbsent = newNumberAbsent; } return numberOfClientsAbsent < 0 ? 0 : numberOfClientsAbsent; } + + private long deadline(final long idleTimeout) + { + return System.currentTimeMillis() + idleTimeout; + } + + private int numberAbsent(int numberOfClientsToAwait) + { + return numberOfClientsToAwait - _registeredClientNames.size(); + } + private void notifyAllWaiters() { synchronized (_lock) diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ResultsForAllTests.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ResultsForAllTests.java index 6c5ff3450c..d4474e2c12 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ResultsForAllTests.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/ResultsForAllTests.java @@ -21,7 +21,9 @@ package org.apache.qpid.disttest.controller; import java.util.ArrayList; import java.util.List; +import org.apache.qpid.disttest.message.ParticipantResult; import org.apache.qpid.disttest.results.aggregation.ITestResult; +import org.apache.qpid.disttest.results.aggregation.TestResultAggregator; public class ResultsForAllTests { @@ -46,4 +48,23 @@ public class ResultsForAllTests { return _hasErrors; } + + public ResultsForAllTests getAllParticipantsResult() + { + ResultsForAllTests summaryResultsForAllTests = new ResultsForAllTests(); + + for (ITestResult testResult : _results) + { + for(ParticipantResult participantResult : testResult.getParticipantResults()) + { + if(TestResultAggregator.ALL_CONSUMER_PARTICIPANTS_NAME.equals(participantResult.getParticipantName())) + { + TestResult summaryTestResult = new TestResult(testResult.getName()); + summaryTestResult.addParticipantResult(participantResult); + summaryResultsForAllTests.add(summaryTestResult); + } + } + } + return summaryResultsForAllTests; + } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java index 110de8a4ea..dcccccdd5f 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ConsumerConfig.java @@ -24,7 +24,6 @@ import org.apache.qpid.disttest.message.CreateConsumerCommand; public class ConsumerConfig extends ParticipantConfig { - private boolean _isTopic; private boolean _isDurableSubscription; private boolean _isBrowsingSubscription; private String _selector; @@ -35,7 +34,6 @@ public class ConsumerConfig extends ParticipantConfig // For Gson public ConsumerConfig() { - _isTopic = false; _isDurableSubscription = false; _isBrowsingSubscription = false; _selector = null; @@ -56,9 +54,8 @@ public class ConsumerConfig extends ParticipantConfig boolean noLocal, boolean synchronous) { - super(consumerName, destinationName, numberOfMessages, batchSize, maximumDuration); + super(consumerName, destinationName, isTopic, numberOfMessages, batchSize, maximumDuration); - _isTopic = isTopic; _isDurableSubscription = isDurableSubscription; _isBrowsingSubscription = isBrowsingSubscription; _selector = selector; @@ -73,7 +70,6 @@ public class ConsumerConfig extends ParticipantConfig setParticipantProperties(createConsumerCommand); createConsumerCommand.setSessionName(sessionName); - createConsumerCommand.setTopic(_isTopic); createConsumerCommand.setDurableSubscription(_isDurableSubscription); createConsumerCommand.setBrowsingSubscription(_isBrowsingSubscription); createConsumerCommand.setSelector(_selector); diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java index 16f7b0d18d..99ae4b7426 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ParticipantConfig.java @@ -33,6 +33,7 @@ public abstract class ParticipantConfig private boolean _alreadyLoggedAboutOverriddenDuration; private String _destinationName; + private boolean _isTopic; private long _numberOfMessages; private String _name; private int _batchSize; @@ -51,12 +52,14 @@ public abstract class ParticipantConfig public ParticipantConfig( String name, String destinationName, + boolean isTopic, long numberOfMessages, int batchSize, long maximumDuration) { _name = name; _destinationName = destinationName; + _isTopic = isTopic; _numberOfMessages = numberOfMessages; _batchSize = batchSize; _maximumDuration = maximumDuration; @@ -66,6 +69,7 @@ public abstract class ParticipantConfig { createParticipantCommand.setParticipantName(_name); createParticipantCommand.setDestinationName(_destinationName); + createParticipantCommand.setTopic(_isTopic); createParticipantCommand.setNumberOfMessages(_numberOfMessages); createParticipantCommand.setBatchSize(_batchSize); diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java index f2369ed671..88c188d3ac 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/controller/config/ProducerConfig.java @@ -59,7 +59,7 @@ public class ProducerConfig extends ParticipantConfig long startDelay, String messageProviderName) { - super(producerName, destinationName, numberOfMessages, batchSize, maximumDuration); + super(producerName, destinationName, false, numberOfMessages, batchSize, maximumDuration); _deliveryMode = deliveryMode; _messageSize = messageSize; diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/db/ResultsDbWriter.java b/java/perftests/src/main/java/org/apache/qpid/disttest/db/ResultsDbWriter.java new file mode 100644 index 0000000000..fdea03ae5e --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/db/ResultsDbWriter.java @@ -0,0 +1,467 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.db; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.ACKNOWLEDGE_MODE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.AVERAGE_LATENCY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.DELIVERY_MODE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSING_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONOUS_CONSUMER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.LATENCY_STANDARD_DEVIATION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MAX_LATENCY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MIN_LATENCY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRIORITY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_INTERVAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_START_DELAY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TAKEN; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TO_LIVE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_CONSUMERS; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_PRODUCERS; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_PAYLOAD_PROCESSED; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Date; +import java.util.Hashtable; +import java.util.TimeZone; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.log4j.Logger; +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.aggregation.ITestResult; + +/** + * Intended call sequence: + *

    + *
  • {@link #ResultsDbWriter(Context, String)}
  • + *
  • {@link #createResultsTableIfNecessary()}
  • + *
  • {@link #writeResults(ResultsForAllTests)} (usually multiple times)
  • + *
+ */ +public class ResultsDbWriter +{ + private static final Logger _logger = Logger.getLogger(ResultsDbWriter.class); + + private static final String RESULTS_TABLE_NAME = "RESULTS"; + + /** column name */ + static final String INSERTED_TIMESTAMP = "insertedTimestamp"; + /** column name */ + static final String RUN_ID = "runId"; + + private static final String TABLE_EXISTENCE_QUERY = "SELECT 1 FROM SYS.SYSTABLES WHERE TABLENAME = ?"; + + private static final String CREATE_RESULTS_TABLE = String.format( + "CREATE TABLE %1$s (" + + "%2$s varchar(200) not null" + // TEST_NAME + ", %3$s bigint not null" + // ITERATION_NUMBER + ", %4$s varchar(200) not null" + // PARTICIPANT_NAME + ", %5$s double not null" + // THROUGHPUT + ", %6$s double" + // AVERAGE_LATENCY + ", %7$s varchar(200)" + // CONFIGURED_CLIENT_NAME + ", %8$s bigint" + // NUMBER_OF_MESSAGES_PROCESSED + ", %9$s bigint" + // PAYLOAD_SIZE + ", %10$s bigint" + // PRIORITY + ", %11$s bigint" + // TIME_TO_LIVE + ", %12$s bigint" + // ACKNOWLEDGE_MODE + ", %13$s bigint" + // DELIVERY_MODE + ", %14$s bigint" + // BATCH_SIZE + ", %15$s bigint" + // MAXIMUM_DURATION + ", %16$s bigint" + // PRODUCER_START_DELAY + ", %17$s bigint" + // PRODUCER_INTERVAL + ", %18$s bigint" + // IS_TOPIC + ", %19$s bigint" + // IS_DURABLE_SUBSCRIPTION + ", %20$s bigint" + // IS_BROWSING_SUBSCRIPTION + ", %21$s bigint" + // IS_SELECTOR + ", %22$s bigint" + // IS_NO_LOCAL + ", %23$s bigint" + // IS_SYNCHRONOUS_CONSUMER + ", %24$s bigint" + // TOTAL_NUMBER_OF_CONSUMERS + ", %25$s bigint" + // TOTAL_NUMBER_OF_PRODUCERS + ", %26$s bigint" + // TOTAL_PAYLOAD_PROCESSED + ", %27$s bigint" + // TIME_TAKEN + ", %28$s varchar(2000)" + // ERROR_MESSAGE + ", %29$s bigint" + // MIN_LATENCY + ", %30$s bigint" + // MAX_LATENCY + ", %31$s double" + // LATENCY_STANDARD_DEVIATION + ", %32$s varchar(200) not null" + + ", %33$s timestamp not null" + + ")", + RESULTS_TABLE_NAME, + TEST_NAME.getDisplayName(), + ITERATION_NUMBER.getDisplayName(), + PARTICIPANT_NAME.getDisplayName(), + THROUGHPUT.getDisplayName(), + AVERAGE_LATENCY.getDisplayName(), + CONFIGURED_CLIENT_NAME.getDisplayName(), + NUMBER_OF_MESSAGES_PROCESSED.getDisplayName(), + PAYLOAD_SIZE.getDisplayName(), + PRIORITY.getDisplayName(), + TIME_TO_LIVE.getDisplayName(), + ACKNOWLEDGE_MODE.getDisplayName(), + DELIVERY_MODE.getDisplayName(), + BATCH_SIZE.getDisplayName(), + MAXIMUM_DURATION.getDisplayName(), + PRODUCER_START_DELAY.getDisplayName(), + PRODUCER_INTERVAL.getDisplayName(), + IS_TOPIC.getDisplayName(), + IS_DURABLE_SUBSCRIPTION.getDisplayName(), + IS_BROWSING_SUBSCRIPTION.getDisplayName(), + IS_SELECTOR.getDisplayName(), + IS_NO_LOCAL.getDisplayName(), + IS_SYNCHRONOUS_CONSUMER.getDisplayName(), + TOTAL_NUMBER_OF_CONSUMERS.getDisplayName(), + TOTAL_NUMBER_OF_PRODUCERS.getDisplayName(), + TOTAL_PAYLOAD_PROCESSED.getDisplayName(), + TIME_TAKEN.getDisplayName(), + ERROR_MESSAGE.getDisplayName(), + MIN_LATENCY.getDisplayName(), + MAX_LATENCY.getDisplayName(), + LATENCY_STANDARD_DEVIATION.getDisplayName(), + RUN_ID, + INSERTED_TIMESTAMP + ); + + public static final String DRIVER_NAME = "jdbcDriverClass"; + public static final String URL = "jdbcUrl"; + + private final String _url; + private final String _runId; + + private final Clock _clock; + + /** + * @param runId may be null, in which case a default value is chosen based on current GMT time + * @param context must contain environment entries {@value #DRIVER_NAME} and {@value #URL}. + */ + public ResultsDbWriter(Context context, String runId) + { + this(context, runId, new Clock()); + } + + /** only call directly from tests */ + ResultsDbWriter(Context context, String runId, Clock clock) + { + _clock = clock; + _runId = defaultIfNullRunId(runId); + + _url = initialiseJdbc(context); + } + + private String defaultIfNullRunId(String runId) + { + if(runId == null) + { + Date dateNow = new Date(_clock.currentTimeMillis()); + Calendar calNow = Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00")); + calNow.setTime(dateNow); + return String.format("run %1$tF %1$tT.%tL", calNow); + } + else + { + return runId; + } + } + + public String getRunId() + { + return _runId; + } + + /** + * Uses the context's environment to load the JDBC driver class and return the + * JDBC URL specified therein. + * @return the JDBC URL + */ + private String initialiseJdbc(Context context) + { + Hashtable environment = null; + try + { + environment = context.getEnvironment(); + + String driverName = (String) environment.get(DRIVER_NAME); + if(driverName == null) + { + throw new IllegalArgumentException("JDBC driver name " + DRIVER_NAME + + " missing from context environment: " + environment); + } + + Class.forName(driverName); + + Object url = environment.get(URL); + if(url == null) + { + throw new IllegalArgumentException("JDBC URL " + URL + " missing from context environment: " + environment); + } + return (String) url; + } + catch (NamingException e) + { + throw constructorRethrow(e, environment); + } + catch (ClassNotFoundException e) + { + throw constructorRethrow(e, environment); + } + } + + private RuntimeException constructorRethrow(Exception e, Hashtable environment) + { + return new RuntimeException("Couldn't initialise ResultsDbWriter from context with environment" + environment, e); + } + + public void createResultsTableIfNecessary() + { + try + { + Connection connection = null; + try + { + connection = DriverManager.getConnection(_url); + if(!tableExists(RESULTS_TABLE_NAME, connection)) + { + Statement statement = connection.createStatement(); + try + { + _logger.info("About to create results table using SQL: " + CREATE_RESULTS_TABLE); + statement.execute(CREATE_RESULTS_TABLE); + } + finally + { + statement.close(); + } + } + } + finally + { + if(connection != null) + { + connection.close(); + } + } + } + catch (SQLException e) + { + throw new RuntimeException("Couldn't create results table", e); + } + + } + + private boolean tableExists(final String tableName, final Connection conn) throws SQLException + { + PreparedStatement stmt = conn.prepareStatement(TABLE_EXISTENCE_QUERY); + try + { + stmt.setString(1, tableName); + ResultSet rs = stmt.executeQuery(); + try + { + return rs.next(); + } + finally + { + rs.close(); + } + } + finally + { + stmt.close(); + } + } + + public void writeResults(ResultsForAllTests results) + { + try + { + writeResultsThrowingException(results); + } + catch (SQLException e) + { + throw new RuntimeException("Couldn't write results " + results, e); + } + _logger.info(this + " wrote " + results.getTestResults().size() + " results to database"); + } + + private void writeResultsThrowingException(ResultsForAllTests results) throws SQLException + { + Connection connection = null; + try + { + connection = DriverManager.getConnection(_url); + + for (ITestResult testResult : results.getTestResults()) + { + for (ParticipantResult participantResult : testResult.getParticipantResults()) + { + writeParticipantResult(connection, participantResult); + } + } + } + finally + { + if(connection != null) + { + connection.close(); + } + } + } + + private void writeParticipantResult(Connection connection, ParticipantResult participantResult) throws SQLException + { + if(_logger.isDebugEnabled()) + { + _logger.debug("About to write to DB the following participant result: " + participantResult); + } + + PreparedStatement statement = null; + try + { + String sqlTemplate = String.format( + "INSERT INTO %s (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) " + + "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + RESULTS_TABLE_NAME, + TEST_NAME.getDisplayName(), + ITERATION_NUMBER.getDisplayName(), + PARTICIPANT_NAME.getDisplayName(), + THROUGHPUT.getDisplayName(), + AVERAGE_LATENCY.getDisplayName(), + CONFIGURED_CLIENT_NAME.getDisplayName(), + NUMBER_OF_MESSAGES_PROCESSED.getDisplayName(), + PAYLOAD_SIZE.getDisplayName(), + PRIORITY.getDisplayName(), + TIME_TO_LIVE.getDisplayName(), + ACKNOWLEDGE_MODE.getDisplayName(), + DELIVERY_MODE.getDisplayName(), + BATCH_SIZE.getDisplayName(), + MAXIMUM_DURATION.getDisplayName(), + PRODUCER_START_DELAY.getDisplayName(), + PRODUCER_INTERVAL.getDisplayName(), + IS_TOPIC.getDisplayName(), + IS_DURABLE_SUBSCRIPTION.getDisplayName(), + IS_BROWSING_SUBSCRIPTION.getDisplayName(), + IS_SELECTOR.getDisplayName(), + IS_NO_LOCAL.getDisplayName(), + IS_SYNCHRONOUS_CONSUMER.getDisplayName(), + TOTAL_NUMBER_OF_CONSUMERS.getDisplayName(), + TOTAL_NUMBER_OF_PRODUCERS.getDisplayName(), + TOTAL_PAYLOAD_PROCESSED.getDisplayName(), + TIME_TAKEN.getDisplayName(), + ERROR_MESSAGE.getDisplayName(), + MIN_LATENCY.getDisplayName(), + MAX_LATENCY.getDisplayName(), + LATENCY_STANDARD_DEVIATION.getDisplayName(), + RUN_ID, + INSERTED_TIMESTAMP + ); + statement = connection.prepareStatement(sqlTemplate); + + int columnIndex = 1; + statement.setString(columnIndex++, participantResult.getTestName()); + statement.setInt(columnIndex++, participantResult.getIterationNumber()); + statement.setString(columnIndex++, participantResult.getParticipantName()); + statement.setDouble(columnIndex++, participantResult.getThroughput()); + statement.setDouble(columnIndex++, participantResult.getAverageLatency()); + statement.setString(columnIndex++, participantResult.getConfiguredClientName()); + statement.setLong(columnIndex++, participantResult.getNumberOfMessagesProcessed()); + statement.setLong(columnIndex++, participantResult.getPayloadSize()); + statement.setLong(columnIndex++, participantResult.getPriority()); + statement.setLong(columnIndex++, participantResult.getTimeToLive()); + statement.setLong(columnIndex++, participantResult.getAcknowledgeMode()); + statement.setLong(columnIndex++, participantResult.getDeliveryMode()); + statement.setLong(columnIndex++, participantResult.getBatchSize()); + statement.setLong(columnIndex++, participantResult.getMaximumDuration()); + statement.setLong(columnIndex++, 0 /* TODO PRODUCER_START_DELAY*/); + statement.setLong(columnIndex++, 0 /* TODO PRODUCER_INTERVAL*/); + statement.setLong(columnIndex++, 0 /* TODO IS_TOPIC*/); + statement.setLong(columnIndex++, 0 /* TODO IS_DURABLE_SUBSCRIPTION*/); + statement.setLong(columnIndex++, 0 /* TODO IS_BROWSING_SUBSCRIPTION*/); + statement.setLong(columnIndex++, 0 /* TODO IS_SELECTOR*/); + statement.setLong(columnIndex++, 0 /* TODO IS_NO_LOCAL*/); + statement.setLong(columnIndex++, 0 /* TODO IS_SYNCHRONOUS_CONSUMER*/); + statement.setLong(columnIndex++, participantResult.getTotalNumberOfConsumers()); + statement.setLong(columnIndex++, participantResult.getTotalNumberOfProducers()); + statement.setLong(columnIndex++, participantResult.getTotalPayloadProcessed()); + statement.setLong(columnIndex++, participantResult.getTimeTaken()); + statement.setString(columnIndex++, participantResult.getErrorMessage()); + statement.setLong(columnIndex++, participantResult.getMinLatency()); + statement.setLong(columnIndex++, participantResult.getMaxLatency()); + statement.setDouble(columnIndex++, participantResult.getLatencyStandardDeviation()); + + statement.setString(columnIndex++, _runId); + statement.setTimestamp(columnIndex++, new Timestamp(_clock.currentTimeMillis())); + + statement.execute(); + connection.commit(); + } + catch(SQLException e) + { + _logger.error("Couldn't write " + participantResult, e); + } + finally + { + if (statement != null) + { + statement.close(); + } + } + } + + public static class Clock + { + public long currentTimeMillis() + { + return System.currentTimeMillis(); + } + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("runId", _runId) + .append("url", _url) + .toString(); + } +} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java index 3f8afc9a9a..f242111dc5 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ClientJmsDelegate.java @@ -218,7 +218,15 @@ public class ClientJmsDelegate synchronized(session) { - final Destination destination = session.createQueue(command.getDestinationName()); + final Destination destination; + if(command.isTopic()) + { + destination = session.createTopic(command.getDestinationName()); + } + else + { + destination = session.createQueue(command.getDestinationName()); + } final MessageProducer jmsProducer = session.createProducer(destination); @@ -373,30 +381,6 @@ public class ClientJmsDelegate } } - public void commitOrAcknowledgeMessage(final Message message, final String sessionName) - { - try - { - final Session session = _testSessions.get(sessionName); - if (session.getTransacted()) - { - synchronized(session) - { - session.commit(); - } - } - else if (message != null && session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) - { - message.acknowledge(); - } - } - catch (final JMSException jmse) - { - throw new DistributedTestException("Unable to commit or acknowledge message on session: " + - sessionName, jmse); - } - } - public int getAcknowledgeMode(final String sessionName) { try @@ -493,31 +477,36 @@ public class ClientJmsDelegate } } - public void rollbackOrRecover(String sessionName) + public void commitOrAcknowledgeMessageIfNecessary(final String sessionName, final Message message) { try { final Session session = _testSessions.get(sessionName); - synchronized(session) + if (session.getTransacted()) { - if (session.getTransacted()) - { - session.rollback(); - } - else if (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) + synchronized(session) { - session.recover(); + session.commit(); } } + else if (message != null && session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) + { + message.acknowledge(); + } } catch (final JMSException jmse) { - throw new DistributedTestException("Unable to rollback or recover on session: " + + throw new DistributedTestException("Unable to commit or acknowledge message on session: " + sessionName, jmse); } } - public void releaseMessage(String sessionName) + public void commitIfNecessary(final String sessionName) + { + commitOrAcknowledgeMessageIfNecessary(sessionName, null); + } + + public void rollbackOrRecoverIfNecessary(String sessionName) { try { @@ -528,7 +517,7 @@ public class ClientJmsDelegate { session.rollback(); } - else + else if (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) { session.recover(); } @@ -536,7 +525,8 @@ public class ClientJmsDelegate } catch (final JMSException jmse) { - LOGGER.warn("Unable to rollback or recover on session: " + sessionName, jmse); + throw new DistributedTestException("Unable to rollback or recover on session: " + + sessionName, jmse); } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java index c80e641e5c..782f7ae2fd 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/ControllerJmsDelegate.java @@ -224,12 +224,12 @@ public class ControllerJmsDelegate public void createQueues(List queues) { - _queueCreator.createQueues(_session, queues); + _queueCreator.createQueues(_connection, _session, queues); } public void deleteQueues(List queues) { - _queueCreator.deleteQueues(_session, queues); + _queueCreator.deleteQueues(_connection, _session, queues); } public void addCommandListener(CommandListener commandListener) diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/NoOpQueueCreator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/NoOpQueueCreator.java index 4d4850eccf..d7e0007b28 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/NoOpQueueCreator.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/NoOpQueueCreator.java @@ -20,18 +20,19 @@ package org.apache.qpid.disttest.jms; import java.util.List; +import javax.jms.Connection; import javax.jms.Session; import org.apache.qpid.disttest.controller.config.QueueConfig; public class NoOpQueueCreator implements QueueCreator { @Override - public void createQueues(Session session, List configs) + public void createQueues(Connection connection, Session session, List configs) { } @Override - public void deleteQueues(Session session, List configs) + public void deleteQueues(Connection connection, Session session, List configs) { } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java index 6874abe7d4..ef2cfb6cd4 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QpidQueueCreator.java @@ -20,21 +20,29 @@ package org.apache.qpid.disttest.jms; import java.util.List; +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; import javax.jms.Session; + import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQSession; import org.apache.qpid.disttest.DistributedTestException; import org.apache.qpid.disttest.controller.config.QueueConfig; +import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + public class QpidQueueCreator implements QueueCreator { private static final Logger LOGGER = LoggerFactory.getLogger(QpidQueueCreator.class); private static final FieldTable EMPTY_QUEUE_BIND_ARGUMENTS = new FieldTable(); + private static final String QUEUE_CREATOR_DRAIN_POLL_TIMEOUT = "qpid.disttest.queue.creator.drainPollTime"; + private static int _drainPollTimeout = Integer.getInteger(QUEUE_CREATOR_DRAIN_POLL_TIMEOUT, 500); @Override - public void createQueues(Session session, List configs) + public void createQueues(Connection connection, Session session, List configs) { AMQSession amqSession = (AMQSession)session; for (QueueConfig queueConfig : configs) @@ -44,12 +52,88 @@ public class QpidQueueCreator implements QueueCreator } @Override - public void deleteQueues(Session session, List configs) + public void deleteQueues(Connection connection, Session session, List configs) { AMQSession amqSession = (AMQSession)session; for (QueueConfig queueConfig : configs) { - deleteQueue(amqSession, queueConfig); + AMQDestination destination = createAMQDestination(amqSession, queueConfig); + + // drainQueue method is added because deletion of queue with a lot + // of messages takes time and might cause the timeout exception + drainQueue(connection, destination); + + deleteQueue(amqSession, destination.getAMQQueueName()); + } + } + + private AMQDestination createAMQDestination(AMQSession amqSession, QueueConfig queueConfig) + { + try + { + return (AMQDestination) amqSession.createQueue(queueConfig.getName()); + } + catch (Exception e) + { + throw new DistributedTestException("Failed to create amq destionation object:" + queueConfig, e); + } + } + + private long getQueueDepth(AMQSession amqSession, AMQDestination destination) + { + try + { + long queueDepth = amqSession.getQueueDepth(destination); + return queueDepth; + } + catch (Exception e) + { + throw new DistributedTestException("Failed to query queue depth:" + destination, e); + } + } + + private void drainQueue(Connection connection, AMQDestination destination) + { + Session noAckSession = null; + try + { + LOGGER.debug("About to drain the queue {}", destination.getQueueName()); + noAckSession = connection.createSession(false, org.apache.qpid.jms.Session.NO_ACKNOWLEDGE); + MessageConsumer messageConsumer = noAckSession.createConsumer(destination); + + long currentQueueDepth = getQueueDepth((AMQSession)noAckSession, destination); + int counter = 0; + while (currentQueueDepth > 0) + { + LOGGER.info("Queue {} has {} message(s)", destination.getQueueName(), currentQueueDepth); + + while(messageConsumer.receive(_drainPollTimeout) != null) + { + counter++; + } + + currentQueueDepth = getQueueDepth((AMQSession)noAckSession, destination); + } + LOGGER.info("Drained {} message(s) from queue {} ", counter, destination.getQueueName()); + messageConsumer.close(); + } + catch (Exception e) + { + throw new DistributedTestException("Failed to drain queue:" + destination, e); + } + finally + { + if (noAckSession != null) + { + try + { + noAckSession.close(); + } + catch (JMSException e) + { + throw new DistributedTestException("Failed to close n/a session:" + noAckSession, e); + } + } } } @@ -66,7 +150,7 @@ public class QpidQueueCreator implements QueueCreator EMPTY_QUEUE_BIND_ARGUMENTS, destination.getExchangeName(), destination, autoDelete); - LOGGER.debug("Created queue " + queueConfig); + LOGGER.debug("Created queue {}", queueConfig); } catch (Exception e) { @@ -74,20 +158,19 @@ public class QpidQueueCreator implements QueueCreator } } - private void deleteQueue(AMQSession session, QueueConfig queueConfig) + private void deleteQueue(AMQSession session, AMQShortString queueName) { try { // The Qpid AMQSession API currently makes the #deleteQueue method protected and the // raw protocol method public. This should be changed then we should switch the below to // use #deleteQueue. - AMQDestination destination = (AMQDestination) session.createQueue(queueConfig.getName()); - session.sendQueueDelete(destination.getAMQQueueName()); - LOGGER.debug("Deleted queue " + queueConfig.getName()); + session.sendQueueDelete(queueName); + LOGGER.debug("Deleted queue {}", queueName); } catch (Exception e) { - throw new DistributedTestException("Failed to delete queue:" + queueConfig.getName(), e); + throw new DistributedTestException("Failed to delete queue:" + queueName, e); } } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QueueCreator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QueueCreator.java index 0947dd53cb..a37cd7888c 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QueueCreator.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/jms/QueueCreator.java @@ -20,12 +20,13 @@ package org.apache.qpid.disttest.jms; import java.util.List; +import javax.jms.Connection; import javax.jms.Session; import org.apache.qpid.disttest.controller.config.QueueConfig; public interface QueueCreator { - public void createQueues(final Session session, final List configs); - public void deleteQueues(final Session session, final List configs); + void createQueues(Connection connection, Session session, List configs); + void deleteQueues(Connection connection, Session session, List configs); } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java index ad9aa31472..e78f6965d2 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ConsumerParticipantResult.java @@ -134,6 +134,7 @@ public class ConsumerParticipantResult extends ParticipantResult _messageLatencies = messageLatencies; } + @Override @OutputAttribute(attribute=ParticipantAttribute.MIN_LATENCY) public long getMinLatency() { @@ -145,6 +146,7 @@ public class ConsumerParticipantResult extends ParticipantResult _minLatency = minLatency; } + @Override @OutputAttribute(attribute=ParticipantAttribute.MAX_LATENCY) public long getMaxLatency() { @@ -156,6 +158,7 @@ public class ConsumerParticipantResult extends ParticipantResult _maxLatency = maxLatency; } + @Override @OutputAttribute(attribute=ParticipantAttribute.AVERAGE_LATENCY) public double getAverageLatency() { @@ -167,6 +170,7 @@ public class ConsumerParticipantResult extends ParticipantResult _averageLatency = averageLatency; } + @Override @OutputAttribute(attribute=ParticipantAttribute.LATENCY_STANDARD_DEVIATION) public double getLatencyStandardDeviation() { diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java index 68c21fbf83..07a60504c8 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateConsumerCommand.java @@ -21,7 +21,6 @@ package org.apache.qpid.disttest.message; public class CreateConsumerCommand extends CreateParticpantCommand { - private boolean _isTopic; private boolean _isDurableSubscription; private boolean _isBrowsingSubscription; private String _selector; @@ -75,16 +74,6 @@ public class CreateConsumerCommand extends CreateParticpantCommand this._noLocal = noLocal; } - public boolean isTopic() - { - return _isTopic; - } - - public void setTopic(boolean isTopic) - { - this._isTopic = isTopic; - } - public boolean isSynchronous() { return _synchronous; diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateParticpantCommand.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateParticpantCommand.java index b1caa6ef75..e7349bf795 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateParticpantCommand.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/CreateParticpantCommand.java @@ -23,6 +23,7 @@ import org.apache.commons.lang.builder.ToStringBuilder; public abstract class CreateParticpantCommand extends Command { + private boolean _isTopic; private String _participantName; private String _sessionName; private String _destinationName; @@ -65,6 +66,16 @@ public abstract class CreateParticpantCommand extends Command _destinationName = destinationName; } + public boolean isTopic() + { + return _isTopic; + } + + public void setTopic(boolean isTopic) + { + _isTopic = isTopic; + } + public long getNumberOfMessages() { return _numberOfMessages; diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java index 0418562a2d..1154ff306c 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantAttribute.java @@ -18,6 +18,8 @@ */ package org.apache.qpid.disttest.message; +import java.text.DecimalFormat; + import org.apache.qpid.disttest.client.Participant; /** @@ -31,6 +33,8 @@ public enum ParticipantAttribute { TEST_NAME("testName"), ITERATION_NUMBER("iterationNumber"), + THROUGHPUT("throughputKbPerS", "#"), + AVERAGE_LATENCY("averageLatency", "#"), CONFIGURED_CLIENT_NAME("clientName"), PARTICIPANT_NAME("participantName"), NUMBER_OF_MESSAGES_PROCESSED("numberOfMessages"), @@ -52,24 +56,56 @@ public enum ParticipantAttribute TOTAL_NUMBER_OF_CONSUMERS("totalNumberOfConsumers"), TOTAL_NUMBER_OF_PRODUCERS("totalNumberOfProducers"), TOTAL_PAYLOAD_PROCESSED("totalPayloadProcessedB"), - THROUGHPUT("throughputKbPerS"), TIME_TAKEN("timeTakenMs"), ERROR_MESSAGE("errorMessage"), MIN_LATENCY("minLatency"), MAX_LATENCY("maxLatency"), - AVERAGE_LATENCY("averageLatency"), - LATENCY_STANDARD_DEVIATION("latencyStandardDeviation") + LATENCY_STANDARD_DEVIATION("latencyStandardDeviation"), + MESSAGE_THROUGHPUT("throughputMessagesPerS") ; private String _displayName; + private String _decimalFormat; ParticipantAttribute(String displayName) { _displayName = displayName; } + ParticipantAttribute(String displayName, String decimalFormat) + { + _displayName = displayName; + _decimalFormat = decimalFormat; + } + + public String getDecimalFormat() + { + return _decimalFormat; + } + public String getDisplayName() { return _displayName; } + + public String format(Object attributeValue) + { + if(attributeValue == null) + { + return null; + } + + String attributeAsString = String.valueOf(attributeValue); + + if(_decimalFormat != null) + { + DecimalFormat decimalFormat = new DecimalFormat(_decimalFormat); + double attributeAsDoule = Double.valueOf(attributeAsString); + return decimalFormat.format(attributeAsDoule); + } + else + { + return attributeAsString; + } + } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java index a6d3d91bae..0a824a316b 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ParticipantResult.java @@ -22,11 +22,12 @@ import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MESSAGE_THROUGHPUT; import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; -import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; import java.util.Comparator; import java.util.Date; @@ -49,6 +50,7 @@ public class ParticipantResult extends Response private long _totalPayloadProcessed; private int _payloadSize; private double _throughput; + private int _messageThroughput; private int _totalNumberOfConsumers; private int _totalNumberOfProducers; @@ -236,6 +238,17 @@ public class ParticipantResult extends Response _throughput = throughput; } + @OutputAttribute(attribute=MESSAGE_THROUGHPUT) + public int getMessageThroughput() + { + return _messageThroughput; + } + + public void setMessageThroughput(int throughput) + { + _messageThroughput = throughput; + } + public void setTotalNumberOfConsumers(int totalNumberOfConsumers) { _totalNumberOfConsumers = totalNumberOfConsumers; @@ -269,4 +282,41 @@ public class ParticipantResult extends Response _acknowledgeMode = acknowledgeMode; } + public double getLatencyStandardDeviation() + { + return 0.0; + } + + @OutputAttribute(attribute = ParticipantAttribute.MIN_LATENCY) + public long getMinLatency() + { + return 0; + } + + @OutputAttribute(attribute = ParticipantAttribute.MAX_LATENCY) + public long getMaxLatency() + { + return 0; + } + + @OutputAttribute(attribute = ParticipantAttribute.AVERAGE_LATENCY) + public double getAverageLatency() + { + return 0; + } + + public int getPriority() + { + return 0; + } + + public long getTimeToLive() + { + return 0; + } + + public int getDeliveryMode() + { + return 0; + } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java index 766c90eec8..2d9399a3d3 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/message/ProducerParticipantResult.java @@ -42,6 +42,7 @@ public class ProducerParticipantResult extends ParticipantResult setParticipantName(participantName); } + @Override @OutputAttribute(attribute=PRIORITY) public int getPriority() { @@ -53,6 +54,7 @@ public class ProducerParticipantResult extends ParticipantResult _priority = priority; } + @Override @OutputAttribute(attribute=TIME_TO_LIVE) public long getTimeToLive() { @@ -86,6 +88,7 @@ public class ProducerParticipantResult extends ParticipantResult _interval = producerInterval; } + @Override @OutputAttribute(attribute=DELIVERY_MODE) public int getDeliveryMode() { @@ -96,5 +99,4 @@ public class ProducerParticipantResult extends ParticipantResult { this._deliveryMode = deliveryMode; } - } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ITestResult.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ITestResult.java index 3f9cdff69d..6230067486 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ITestResult.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ITestResult.java @@ -22,10 +22,8 @@ import java.util.List; import org.apache.qpid.disttest.message.ParticipantResult; -// TODO rename me!! public interface ITestResult { - // TODO should weaken to Collection List getParticipantResults(); diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java index 4dcabe6c7b..c21a78d359 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregator.java @@ -142,6 +142,7 @@ public class ParticipantResultAggregator aggregatedResult.setStartDate(new Date(_minStartDate)); aggregatedResult.setEndDate(new Date(_maxEndDate)); aggregatedResult.setThroughput(calculateThroughputInKiloBytesPerSecond()); + aggregatedResult.setMessageThroughput(calculateThroughputInMessagesPerSecond()); } private void setRolledUpConstantAttributes(ParticipantResult aggregatedResult) @@ -197,4 +198,14 @@ public class ParticipantResultAggregator return totalPayloadProcessedInKiloBytes/durationInSeconds; } + private int calculateThroughputInMessagesPerSecond() + { + double durationInMillis = _maxEndDate - _minStartDate; + if (durationInMillis == 0 ) + { + return 0; + } + + return (int)Math.round((_numberOfMessagesProcessed * 1000.0d)/durationInMillis); + } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregator.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregator.java index 5934e0e997..954828b043 100644 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregator.java +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregator.java @@ -18,6 +18,9 @@ */ package org.apache.qpid.disttest.results.aggregation; +import java.util.List; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; import org.apache.qpid.disttest.message.ConsumerParticipantResult; import org.apache.qpid.disttest.message.ParticipantResult; import org.apache.qpid.disttest.message.ProducerParticipantResult; @@ -102,5 +105,26 @@ public class TestResultAggregator aggregatedAllResult.setNumberOfMessagesProcessed(aggregatedConsumerResult.getNumberOfMessagesProcessed()); aggregatedAllResult.setTotalPayloadProcessed(aggregatedConsumerResult.getTotalPayloadProcessed()); aggregatedAllResult.setThroughput(aggregatedConsumerResult.getThroughput()); + aggregatedAllResult.setMessageThroughput(aggregatedConsumerResult.getMessageThroughput()); + } + + /** + * Produces a single {@link ResultsForAllTests} from the supplied list, only containing + * the "All participants" results. + */ + public ResultsForAllTests aggregateTestResults(List allResultsList) + { + ResultsForAllTests retVal = new ResultsForAllTests(); + + for (ResultsForAllTests resultsForAllTests : allResultsList) + { + ResultsForAllTests allParticipantsResult = resultsForAllTests.getAllParticipantsResult(); + for (ITestResult testResult : allParticipantsResult.getTestResults()) + { + retVal.add(testResult); + } + } + + return retVal; } } diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormater.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormater.java deleted file mode 100644 index 52e53ca624..0000000000 --- a/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormater.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpid.disttest.results.formatting; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang.StringUtils; -import org.apache.qpid.disttest.controller.ResultsForAllTests; -import org.apache.qpid.disttest.message.ParticipantAttribute; -import org.apache.qpid.disttest.message.ParticipantResult; -import org.apache.qpid.disttest.results.aggregation.ITestResult; - -/** - * produces CSV output using the ordered enums in {@link ParticipantAttribute} - */ -public class CSVFormater -{ - public String format(ResultsForAllTests results) - { - StringBuilder builder = new StringBuilder(); - - builder.append(header()); - - List testResults = results.getTestResults(); - - for (ITestResult testResult : testResults) - { - - List participantResults = new ArrayList(testResult.getParticipantResults()); - Collections.sort(participantResults, new CSVOrderParticipantResultComparator()); - - for (ParticipantResult participantResult : participantResults) - { - Map attributes = participantResult.getAttributes(); - builder.append(row(attributes)); - } - } - - return builder.toString(); - } - - /** - * return a row, including a newline character at the end - */ - private String row(Map attributeValueMap) - { - List attributeValues = new ArrayList(); - for (ParticipantAttribute attribute : ParticipantAttribute.values()) - { - attributeValues.add(attributeValueMap.get(attribute)); - } - - String row = StringUtils.join(attributeValues.toArray(), ","); - return row + "\n"; - } - - /** return the header row, including a newline at the end */ - private String header() - { - List displayNames = new ArrayList(); - for (ParticipantAttribute attribute : ParticipantAttribute.values()) - { - displayNames.add(attribute.getDisplayName()); - } - - String header = StringUtils.join(displayNames.toArray(), ","); - return header + "\n"; - } - -} diff --git a/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormatter.java b/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormatter.java new file mode 100644 index 0000000000..ea7a3f78c7 --- /dev/null +++ b/java/perftests/src/main/java/org/apache/qpid/disttest/results/formatting/CSVFormatter.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.formatting; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.message.ParticipantAttribute; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.aggregation.ITestResult; + +/** + * produces CSV output using the ordered enums in {@link ParticipantAttribute} + */ +public class CSVFormatter +{ + public String format(ResultsForAllTests results) + { + StringBuilder builder = new StringBuilder(); + + builder.append(header()); + + List testResults = results.getTestResults(); + + for (ITestResult testResult : testResults) + { + + List participantResults = new ArrayList(testResult.getParticipantResults()); + Collections.sort(participantResults, new CSVOrderParticipantResultComparator()); + + for (ParticipantResult participantResult : participantResults) + { + Map attributes = participantResult.getAttributes(); + builder.append(row(attributes)); + } + } + + return builder.toString(); + } + + /** + * return a row, including a newline character at the end + */ + private String row(Map attributeValueMap) + { + List attributeValues = new ArrayList(); + for (ParticipantAttribute attribute : ParticipantAttribute.values()) + { + Object attributeValue = attributeValueMap.get(attribute); + String attributeValueFormatted = attribute.format(attributeValue); + attributeValues.add(attributeValueFormatted); + } + + String row = StringUtils.join(attributeValues.toArray(), ","); + return row + "\n"; + } + + /** return the header row, including a newline at the end */ + private String header() + { + List displayNames = new ArrayList(); + for (ParticipantAttribute attribute : ParticipantAttribute.values()) + { + displayNames.add(attribute.getDisplayName()); + } + + String header = StringUtils.join(displayNames.toArray(), ","); + return header + "\n"; + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelperTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelperTest.java index a10b3b359e..629442d86c 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelperTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/ConfigFileHelperTest.java @@ -39,14 +39,6 @@ public class ConfigFileHelperTest extends QpidTestCase _testDir = TestFileUtils.createTestDirectory(); } - public void testGenerateOutputCsvNameFrom() - { - String outputDir = "/tmp/outputDir"; - - assertEquals("/tmp/outputDir/my.json.file.csv", _configFileHelper.generateOutputCsvNameFrom("/tmp/my.json.file.json", outputDir)); - assertEquals("/tmp/outputDir/my.js.file.csv", _configFileHelper.generateOutputCsvNameFrom("/tmp/my.js.file.js", outputDir)); - } - public void testGetTestConfigFilesForDirectory() throws Exception { String jsFile = createFile("file1.js"); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/ResultsFileWriterTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/ResultsFileWriterTest.java new file mode 100644 index 0000000000..ab55e8003d --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/ResultsFileWriterTest.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.Arrays; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.results.aggregation.TestResultAggregator; +import org.apache.qpid.disttest.results.formatting.CSVFormatter; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.util.FileUtils; + +public class ResultsFileWriterTest extends QpidTestCase +{ + private CSVFormatter _csvFormater = mock(CSVFormatter.class); + private TestResultAggregator _testResultAggregator = mock(TestResultAggregator.class); + + private File _outputDir = TestFileUtils.createTestDirectory(); + + private ResultsFileWriter _resultsFileWriter = new ResultsFileWriter(_outputDir); + + @Override + public void setUp() + { + _resultsFileWriter.setCsvFormater(_csvFormater); + _resultsFileWriter.setTestResultAggregator(_testResultAggregator); + } + + public void testWriteResultsToFile() + { + ResultsForAllTests resultsForAllTests = mock(ResultsForAllTests.class); + + String expectedCsvContents = "expected-csv-contents"; + when(_csvFormater.format(resultsForAllTests)).thenReturn(expectedCsvContents); + + _resultsFileWriter.writeResultsToFile(resultsForAllTests, "config.json"); + + File resultsFile = new File(_outputDir, "config.csv"); + + assertEquals(expectedCsvContents, FileUtils.readFileAsString(resultsFile)); + } + + public void testWriteResultsSummary() + { + ResultsForAllTests results1 = mock(ResultsForAllTests.class); + ResultsForAllTests results2 = mock(ResultsForAllTests.class); + ResultsForAllTests summaryResults = mock(ResultsForAllTests.class); + + when(_testResultAggregator.aggregateTestResults(Arrays.asList(results1, results2))) + .thenReturn(summaryResults); + + String expectedSummaryFileContents = "expected-summary-file"; + + when(_csvFormater.format(summaryResults)) + .thenReturn(expectedSummaryFileContents); + + _resultsFileWriter.writeResultsSummary(Arrays.asList(results1, results2)); + + File summaryFile = new File(_outputDir, ResultsFileWriter.TEST_SUMMARY_FILE_NAME); + + assertEquals(expectedSummaryFileContents, FileUtils.readFileAsString(summaryFile)); + } + +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/VisitorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/VisitorTest.java index 320e7d8c9d..09f7da4efb 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/VisitorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/VisitorTest.java @@ -19,12 +19,11 @@ */ package org.apache.qpid.disttest; -import junit.framework.TestCase; - import org.apache.qpid.disttest.message.Command; +import org.apache.qpid.test.utils.QpidTestCase; -public class VisitorTest extends TestCase +public class VisitorTest extends QpidTestCase { public void testStringVisited() throws Exception diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientCommandVisitorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientCommandVisitorTest.java index 4a82f6719f..2b29471558 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientCommandVisitorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientCommandVisitorTest.java @@ -21,7 +21,6 @@ package org.apache.qpid.disttest.client; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; -import junit.framework.TestCase; import org.apache.qpid.disttest.jms.ClientJmsDelegate; import org.apache.qpid.disttest.message.CreateConnectionCommand; @@ -32,8 +31,9 @@ import org.apache.qpid.disttest.message.CreateSessionCommand; import org.apache.qpid.disttest.message.StartTestCommand; import org.apache.qpid.disttest.message.StopClientCommand; import org.apache.qpid.disttest.message.TearDownTestCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class ClientCommandVisitorTest extends TestCase +public class ClientCommandVisitorTest extends QpidTestCase { private Client _client; private ClientCommandVisitor _visitor; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java index dd50766918..8139961fa4 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ClientTest.java @@ -29,17 +29,16 @@ import java.util.Collections; import java.util.Timer; import java.util.TimerTask; -import junit.framework.TestCase; - import org.apache.qpid.disttest.jms.ClientJmsDelegate; import org.apache.qpid.disttest.message.Command; import org.apache.qpid.disttest.message.ParticipantResult; import org.apache.qpid.disttest.message.Response; import org.apache.qpid.disttest.message.StopClientCommand; +import org.apache.qpid.test.utils.QpidTestCase; import org.mockito.InOrder; import org.mockito.Mockito; -public class ClientTest extends TestCase +public class ClientTest extends QpidTestCase { private Client _client; private ClientJmsDelegate _delegate; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java index 58589d36f4..f75415a2bf 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ConsumerParticipantTest.java @@ -34,16 +34,15 @@ import java.util.Collection; import javax.jms.Message; import javax.jms.Session; -import junit.framework.TestCase; - import org.apache.qpid.disttest.DistributedTestException; import org.apache.qpid.disttest.jms.ClientJmsDelegate; import org.apache.qpid.disttest.message.ConsumerParticipantResult; import org.apache.qpid.disttest.message.CreateConsumerCommand; import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.test.utils.QpidTestCase; import org.mockito.InOrder; -public class ConsumerParticipantTest extends TestCase +public class ConsumerParticipantTest extends QpidTestCase { private static final String SESSION_NAME1 = "SESSION1"; private static final String PARTICIPANT_NAME1 = "PARTICIPANT_NAME1"; @@ -114,7 +113,7 @@ public class ConsumerParticipantTest extends TestCase _inOrder.verify(_delegate).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT); _inOrder.verify(_delegate).calculatePayloadSizeFrom(_mockMessage); - _inOrder.verify(_delegate).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + _inOrder.verify(_delegate).commitOrAcknowledgeMessageIfNecessary(SESSION_NAME1, _mockMessage); } public void testReceiveMessagesForDurationSynch() throws Exception @@ -129,7 +128,7 @@ public class ConsumerParticipantTest extends TestCase verify(_delegate, atLeastOnce()).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT); verify(_delegate, atLeastOnce()).calculatePayloadSizeFrom(_mockMessage); - verify(_delegate, atLeastOnce()).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + verify(_delegate, atLeastOnce()).commitOrAcknowledgeMessageIfNecessary(SESSION_NAME1, _mockMessage); } public void testReceiveMessagesBatchedSynch() throws Exception @@ -147,7 +146,7 @@ public class ConsumerParticipantTest extends TestCase verify(_delegate, times(numberOfMessages)).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT); verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); - verify(_delegate, times(4)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + verify(_delegate, times(4)).commitOrAcknowledgeMessageIfNecessary(SESSION_NAME1, _mockMessage); } public void testReceiveMessagesWithVaryingPayloadSize() throws Exception @@ -171,7 +170,7 @@ public class ConsumerParticipantTest extends TestCase verify(_delegate, times(numberOfMessages)).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT); verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); - verify(_delegate, times(numberOfMessages)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + verify(_delegate, times(numberOfMessages)).commitOrAcknowledgeMessageIfNecessary(SESSION_NAME1, _mockMessage); } public void testReleaseResources() @@ -194,7 +193,7 @@ public class ConsumerParticipantTest extends TestCase _inOrder.verify(_delegate).consumeMessage(PARTICIPANT_NAME1, RECEIVE_TIMEOUT); _inOrder.verify(_delegate).calculatePayloadSizeFrom(_mockMessage); - _inOrder.verify(_delegate).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + _inOrder.verify(_delegate).commitOrAcknowledgeMessageIfNecessary(SESSION_NAME1, _mockMessage); assertTrue("Unexpected consuemr results", result instanceof ConsumerParticipantResult); Collection latencies = ((ConsumerParticipantResult)result).getMessageLatencies(); assertNotNull("Message latency is not cllected", latencies); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java index 1ff8d3e5d7..8863e0f289 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/MessageProviderTest.java @@ -33,14 +33,13 @@ import javax.jms.Message; import javax.jms.Session; import javax.jms.TextMessage; -import junit.framework.TestCase; - import org.apache.qpid.disttest.client.property.ListPropertyValue; import org.apache.qpid.disttest.client.property.PropertyValue; import org.apache.qpid.disttest.client.property.SimplePropertyValue; import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class MessageProviderTest extends TestCase +public class MessageProviderTest extends QpidTestCase { private Session _session; private TextMessage _message; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantExecutorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantExecutorTest.java index f30e4664ff..6720047cd1 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantExecutorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantExecutorTest.java @@ -20,6 +20,7 @@ package org.apache.qpid.disttest.client; import static org.mockito.Matchers.argThat; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -28,14 +29,13 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -import junit.framework.TestCase; - import org.apache.qpid.disttest.DistributedTestException; import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.test.utils.QpidTestCase; import org.mockito.ArgumentMatcher; import org.mockito.InOrder; -public class ParticipantExecutorTest extends TestCase +public class ParticipantExecutorTest extends QpidTestCase { private static final ResultHasError HAS_ERROR = new ResultHasError(); private static final String CLIENT_NAME = "CLIENT_NAME"; @@ -69,8 +69,8 @@ public class ParticipantExecutorTest extends TestCase InOrder inOrder = inOrder(_participant, _client); inOrder.verify(_participant).doIt(CLIENT_NAME); - inOrder.verify(_client).sendResults(_mockResult); inOrder.verify(_participant).releaseResources(); + inOrder.verify(_client).sendResults(_mockResult); } public void testParticipantThrowsException() throws Exception @@ -82,13 +82,28 @@ public class ParticipantExecutorTest extends TestCase InOrder inOrder = inOrder(_participant, _client); inOrder.verify(_participant).doIt(CLIENT_NAME); + inOrder.verify(_participant).releaseResources(); inOrder.verify(_client).sendResults(argThat(HAS_ERROR)); + } + + public void testReleaseResourcesThrowsException() throws Exception + { + when(_participant.doIt(CLIENT_NAME)).thenReturn(_mockResult); + doThrow(DistributedTestException.class).when(_participant).releaseResources(); + + _participantExecutor.start(_client); + + InOrder inOrder = inOrder(_participant, _client); + + inOrder.verify(_participant).doIt(CLIENT_NAME); inOrder.verify(_participant).releaseResources(); + + // check that sendResults is called even though releaseResources threw an exception + inOrder.verify(_client).sendResults(_mockResult); } public void testThreadNameAndDaemonness() throws Exception { - ThreadPropertyReportingParticipant participant = new ThreadPropertyReportingParticipant(PARTICIPANT_NAME); _participantExecutor = new ParticipantExecutor(participant); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantRegistryTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantRegistryTest.java index bd0d5a39c8..5cc8d2f30a 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantRegistryTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantRegistryTest.java @@ -20,9 +20,10 @@ package org.apache.qpid.disttest.client; import static org.mockito.Mockito.mock; -import junit.framework.TestCase; -public class ParticipantRegistryTest extends TestCase +import org.apache.qpid.test.utils.QpidTestCase; + +public class ParticipantRegistryTest extends QpidTestCase { private ParticipantExecutorRegistry _participantRegistry = new ParticipantExecutorRegistry(); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantResultFactoryTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantResultFactoryTest.java index 3b21834a5c..9eab459443 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantResultFactoryTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ParticipantResultFactoryTest.java @@ -22,16 +22,15 @@ import java.util.Date; import javax.jms.DeliveryMode; -import junit.framework.TestCase; - import org.apache.qpid.disttest.message.ConsumerParticipantResult; import org.apache.qpid.disttest.message.CreateConsumerCommand; import org.apache.qpid.disttest.message.CreateParticpantCommand; import org.apache.qpid.disttest.message.CreateProducerCommand; import org.apache.qpid.disttest.message.ParticipantResult; import org.apache.qpid.disttest.message.ProducerParticipantResult; +import org.apache.qpid.test.utils.QpidTestCase; -public class ParticipantResultFactoryTest extends TestCase +public class ParticipantResultFactoryTest extends QpidTestCase { private static final String PARTICIPANT_NAME = "participantName"; private static final String REGISTERED_CLIENT_NAME = "registeredClientName"; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java index a3ac11b756..08ee8715fd 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/ProducerParticipantTest.java @@ -31,15 +31,14 @@ import javax.jms.DeliveryMode; import javax.jms.Message; import javax.jms.Session; -import junit.framework.TestCase; - import org.apache.qpid.disttest.DistributedTestException; import org.apache.qpid.disttest.jms.ClientJmsDelegate; import org.apache.qpid.disttest.message.CreateProducerCommand; import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.test.utils.QpidTestCase; import org.mockito.InOrder; -public class ProducerParticipantTest extends TestCase +public class ProducerParticipantTest extends QpidTestCase { private ProducerParticipant _producer; @@ -127,13 +126,13 @@ public class ProducerParticipantTest extends TestCase _inOrder.verify(_delegate).sendNextMessage(isA(CreateProducerCommand.class)); _inOrder.verify(_delegate).calculatePayloadSizeFrom(_mockMessage); - _inOrder.verify(_delegate).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + _inOrder.verify(_delegate).commitIfNecessary(SESSION_NAME1); } public void testSendMessagesForDuration() throws Exception { - final long duration = 100; + final long duration = 1000; _command.setMaximumDuration(duration); ParticipantResult result = _producer.doIt(CLIENT_NAME); @@ -142,7 +141,24 @@ public class ProducerParticipantTest extends TestCase verify(_delegate, atLeastOnce()).sendNextMessage(isA(CreateProducerCommand.class)); verify(_delegate, atLeastOnce()).calculatePayloadSizeFrom(_mockMessage); - verify(_delegate, atLeastOnce()).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + verify(_delegate, atLeastOnce()).commitIfNecessary(SESSION_NAME1); + } + + public void testSendMessagesForDurationWithDelayExceedingDuration() throws Exception + { + final long duration = 100; + _command.setMaximumDuration(duration); + _command.setStartDelay(150); + + try + { + _producer.doIt(CLIENT_NAME); + fail("Exception should be thrown indicating configuration error"); + } + catch(DistributedTestException e) + { + assertEquals("Start delay must be less than maximum test duration", e.getMessage()); + } } public void testSendMessageBatches() throws Exception @@ -161,7 +177,7 @@ public class ProducerParticipantTest extends TestCase verify(_delegate, times(numberOfMessages)).sendNextMessage(isA(CreateProducerCommand.class)); verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); - verify(_delegate, times(expectedNumberOfCommits)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + verify(_delegate, times(expectedNumberOfCommits)).commitIfNecessary(SESSION_NAME1); } public void testSendMessageWithPublishInterval() throws Exception @@ -183,7 +199,7 @@ public class ProducerParticipantTest extends TestCase verify(_delegate, times(numberOfMessages)).sendNextMessage(isA(CreateProducerCommand.class)); verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); - verify(_delegate, times(4)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + verify(_delegate, times(4)).commitIfNecessary(SESSION_NAME1); } public void testSendMessageWithVaryingPayloadSize() throws Exception @@ -208,7 +224,7 @@ public class ProducerParticipantTest extends TestCase verify(_delegate, times(numberOfMessages)).sendNextMessage(isA(CreateProducerCommand.class)); verify(_delegate, times(numberOfMessages)).calculatePayloadSizeFrom(_mockMessage); - verify(_delegate, times(numberOfMessages)).commitOrAcknowledgeMessage(_mockMessage, SESSION_NAME1); + verify(_delegate, times(numberOfMessages)).commitIfNecessary(SESSION_NAME1); } public void testReleaseResources() diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java index c54355bc76..3172eb07ed 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/ListPropertyValueTest.java @@ -21,13 +21,9 @@ package org.apache.qpid.disttest.client.property; import java.util.ArrayList; import java.util.List; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.disttest.client.property.ListPropertyValue; -import org.apache.qpid.disttest.client.property.PropertyValue; -import org.apache.qpid.disttest.client.property.SimplePropertyValue; - -public class ListPropertyValueTest extends TestCase +public class ListPropertyValueTest extends QpidTestCase { private ListPropertyValue _generator; private List _items; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java index 17397db5b8..eba1bcc435 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/PropertyValueFactoryTest.java @@ -18,9 +18,9 @@ */ package org.apache.qpid.disttest.client.property; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class PropertyValueFactoryTest extends TestCase +public class PropertyValueFactoryTest extends QpidTestCase { private PropertyValueFactory _factory; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java index 878141895c..9651dd95ce 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RandomPropertyValueTest.java @@ -18,11 +18,9 @@ */ package org.apache.qpid.disttest.client.property; -import org.apache.qpid.disttest.client.property.RandomPropertyValue; +import org.apache.qpid.test.utils.QpidTestCase; -import junit.framework.TestCase; - -public class RandomPropertyValueTest extends TestCase +public class RandomPropertyValueTest extends QpidTestCase { private RandomPropertyValue _generator; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java index 6932919bed..b0649a49ae 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/RangePropertyValueTest.java @@ -18,11 +18,9 @@ */ package org.apache.qpid.disttest.client.property; -import org.apache.qpid.disttest.client.property.RangePropertyValue; +import org.apache.qpid.test.utils.QpidTestCase; -import junit.framework.TestCase; - -public class RangePropertyValueTest extends TestCase +public class RangePropertyValueTest extends QpidTestCase { private RangePropertyValue _generator; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/SimplePropertyValueTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/SimplePropertyValueTest.java index a347d866c7..f1977015fe 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/SimplePropertyValueTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/property/SimplePropertyValueTest.java @@ -18,9 +18,9 @@ */ package org.apache.qpid.disttest.client.property; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class SimplePropertyValueTest extends TestCase +public class SimplePropertyValueTest extends QpidTestCase { public void testGetValue() { diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimitsTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimitsTest.java index 37820d2582..0880512333 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimitsTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithNoLimitsTest.java @@ -25,9 +25,9 @@ import static org.mockito.Mockito.when; import java.util.concurrent.Callable; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class ExecutorWithNoLimitsTest extends TestCase +public class ExecutorWithNoLimitsTest extends QpidTestCase { private final static Object RESULT = new Object(); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimitTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimitTest.java index a201a7bacf..2abdba2446 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimitTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/client/utils/ExecutorWithTimeLimitTest.java @@ -20,16 +20,16 @@ package org.apache.qpid.disttest.client.utils; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.never; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class ExecutorWithTimeLimitTest extends TestCase +public class ExecutorWithTimeLimitTest extends QpidTestCase { private static final int TIMEOUT = 500; private static final Object RESULT = new Object(); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ClientRegistryTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ClientRegistryTest.java index cc969e1ef2..c07d9fcb81 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ClientRegistryTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ClientRegistryTest.java @@ -21,14 +21,15 @@ package org.apache.qpid.disttest.controller; import java.util.Timer; import java.util.TimerTask; -import junit.framework.TestCase; - import org.apache.qpid.disttest.DistributedTestException; +import org.apache.qpid.test.utils.QpidTestCase; -public class ClientRegistryTest extends TestCase +public class ClientRegistryTest extends QpidTestCase { private static final String CLIENT1_REGISTERED_NAME = "CLIENT1_REGISTERED_NAME"; private static final String CLIENT2_REGISTERED_NAME = "CLIENT2_REGISTERED_NAME"; + private static final String CLIENT3_REGISTERED_NAME = "CLIENT3_REGISTERED_NAME"; + private static final int AWAIT_DELAY = 100; private ClientRegistry _clientRegistry = new ClientRegistry(); @@ -70,7 +71,7 @@ public class ClientRegistryTest extends TestCase assertEquals(0, numberOfClientsAbsent); } - public void testAwaitTwoClientWhenClientRegistersWhilstWaiting() + public void testAwaitTwoClientsWhenClientRegistersWhilstWaiting() { _clientRegistry.registerClient(CLIENT1_REGISTERED_NAME); registerClientLater(CLIENT2_REGISTERED_NAME, 50); @@ -79,6 +80,41 @@ public class ClientRegistryTest extends TestCase assertEquals(0, numberOfClientsAbsent); } + public void testAwaitTimeoutForPromptRegistrations() + { + registerClientsLaterAndAssertResult("Clients registering every 100ms should be within 600ms timeout", + new int[] {300, 400, 500}, + 600, + 0); + } + + public void testAwaitTimeoutForWhenThirdRegistrationIsLate() + { + registerClientsLaterAndAssertResult("Third client registering tardily should exceed timeout", + new int[] {300, 400, 1500}, + 600, + 1); + } + + public void testAwaitTimeoutWhenSecondAndThirdRegistrationsAreLate() + { + registerClientsLaterAndAssertResult("Second and third clients registering tardily should exceed timeout", + new int[] {300, 1500, 1500}, + 600, + 2); + } + + private void registerClientsLaterAndAssertResult(String message, int[] registrationDelays, int timeout, int expectedNumberOfAbsentees) + { + registerClientLater(CLIENT1_REGISTERED_NAME, registrationDelays[0]); + registerClientLater(CLIENT2_REGISTERED_NAME, registrationDelays[1]); + registerClientLater(CLIENT3_REGISTERED_NAME, registrationDelays[2]); + + int numberOfClientsAbsent = _clientRegistry.awaitClients(3, timeout); + + assertEquals(message, expectedNumberOfAbsentees, numberOfClientsAbsent); + } + private void registerClientLater(final String clientName, long delayInMillis) { doLater(new TimerTask() diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ControllerTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ControllerTest.java index bc58ea41c5..f773c727a1 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ControllerTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ControllerTest.java @@ -19,6 +19,8 @@ */ package org.apache.qpid.disttest.controller; +import static org.apache.qpid.systest.disttest.SystemTestConstants.COMMAND_RESPONSE_TIMEOUT; +import static org.apache.qpid.systest.disttest.SystemTestConstants.REGISTRATION_TIMEOUT; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isA; @@ -31,8 +33,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import junit.framework.TestCase; - import org.apache.qpid.disttest.DistributedTestException; import org.apache.qpid.disttest.controller.config.Config; import org.apache.qpid.disttest.controller.config.TestInstance; @@ -42,16 +42,14 @@ import org.apache.qpid.disttest.message.RegisterClientCommand; import org.apache.qpid.disttest.message.Response; import org.apache.qpid.disttest.message.StopClientCommand; import org.apache.qpid.disttest.results.aggregation.ITestResult; +import org.apache.qpid.test.utils.QpidTestCase; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -public class ControllerTest extends TestCase +public class ControllerTest extends QpidTestCase { private static final String CLIENT1_REGISTERED_NAME = "client-uid1"; - private static final long COMMAND_RESPONSE_TIMEOUT = 1000; - private static final long REGISTRATION_TIMEOUT = 1000; - private Controller _controller; private ControllerJmsDelegate _respondingJmsDelegate; private TestRunner _testRunner; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ParticipatingClientsTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ParticipatingClientsTest.java index 284db38f44..da180f328f 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ParticipatingClientsTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/ParticipatingClientsTest.java @@ -25,9 +25,9 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class ParticipatingClientsTest extends TestCase +public class ParticipatingClientsTest extends QpidTestCase { private static final String CLIENT1_CONFIGURED_NAME = "CLIENT1_CONFIGURED_NAME"; private static final String CLIENT2_CONFIGURED_NAME = "CLIENT2_CONFIGURED_NAME"; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/TestRunnerTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/TestRunnerTest.java index 983da299b9..d8b25e76fa 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/TestRunnerTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/TestRunnerTest.java @@ -32,8 +32,6 @@ import java.util.List; import java.util.Timer; import java.util.TimerTask; -import junit.framework.TestCase; - import org.apache.qpid.disttest.DistributedTestException; import org.apache.qpid.disttest.controller.config.QueueConfig; import org.apache.qpid.disttest.controller.config.TestInstance; @@ -45,10 +43,11 @@ import org.apache.qpid.disttest.message.ParticipantResult; import org.apache.qpid.disttest.message.Response; import org.apache.qpid.disttest.message.StartTestCommand; import org.apache.qpid.disttest.message.TearDownTestCommand; +import org.apache.qpid.test.utils.QpidTestCase; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -public class TestRunnerTest extends TestCase +public class TestRunnerTest extends QpidTestCase { private static final String TEST_NAME = "TEST_NAME"; private static final String PARTICIPANT_NAME = "TEST_PARTICIPANT_NAME"; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ClientConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ClientConfigTest.java index d4af439dea..4bf4307eaf 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ClientConfigTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ClientConfigTest.java @@ -29,16 +29,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import junit.framework.TestCase; - import org.apache.qpid.disttest.client.property.PropertyValue; import org.apache.qpid.disttest.client.property.SimplePropertyValue; import org.apache.qpid.disttest.controller.CommandForClient; import org.apache.qpid.disttest.message.Command; import org.apache.qpid.disttest.message.CreateMessageProviderCommand; import org.apache.qpid.disttest.message.NoOpCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class ClientConfigTest extends TestCase +public class ClientConfigTest extends QpidTestCase { private static final String CLIENT1 = "client1"; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest-test-config.js b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest-test-config.js index 07f8bf9d92..527300eff4 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest-test-config.js +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest-test-config.js @@ -1,3 +1,23 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ jsonObject = { "_tests": QPID.iterations( { "__ACK_MODE": [ 0, 1 ] }, @@ -31,4 +51,4 @@ jsonObject = { ) }) -} \ No newline at end of file +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java index 257f139849..e208945901 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigReaderTest.java @@ -23,12 +23,12 @@ import java.io.Reader; import java.util.List; import java.util.Map; -import junit.framework.TestCase; - import org.apache.qpid.disttest.ConfigFileTestHelper; import org.apache.qpid.disttest.client.property.PropertyValue; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; -public class ConfigReaderTest extends TestCase +public class ConfigReaderTest extends QpidTestCase { private Config _config; @@ -111,8 +111,9 @@ public class ConfigReaderTest extends TestCase public void testReadsJS() throws Exception { ConfigReader configReader = new ConfigReader(); - String path = getClass().getResource("ConfigReaderTest-test-config.js").toURI().getPath(); + String path = TestFileUtils.createTempFileFromResource(this, "ConfigReaderTest-test-config.js").getAbsolutePath(); _config = configReader.getConfigFromFile(path); + List testConfigs = _config.getTestConfigs(); assertEquals("Unexpected number of tests", 2, testConfigs.size()); TestConfig testConfig1 = _config.getTestConfigs().get(0); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTest.java index 88750b9737..291ce2af78 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConfigTest.java @@ -24,9 +24,9 @@ import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.List; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class ConfigTest extends TestCase +public class ConfigTest extends QpidTestCase { public void testGetTestsForTestWithIteratingMessageSizes() { diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConnectionConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConnectionConfigTest.java index 7c839ed462..0eee80e425 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConnectionConfigTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConnectionConfigTest.java @@ -27,13 +27,12 @@ import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.List; -import junit.framework.TestCase; - import org.apache.qpid.disttest.message.Command; import org.apache.qpid.disttest.message.CreateConnectionCommand; import org.apache.qpid.disttest.message.NoOpCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class ConnectionConfigTest extends TestCase +public class ConnectionConfigTest extends QpidTestCase { private static final String CONNECTION_FACTORY_NAME = "ConnectionFactoryName"; private static final String CONNECTION_NAME = "ConnectionName"; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConsumerConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConsumerConfigTest.java index c011ff4711..0aa05a176e 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConsumerConfigTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ConsumerConfigTest.java @@ -19,11 +19,10 @@ */ package org.apache.qpid.disttest.controller.config; -import junit.framework.TestCase; - import org.apache.qpid.disttest.message.CreateConsumerCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class ConsumerConfigTest extends TestCase +public class ConsumerConfigTest extends QpidTestCase { public void testConsumerHasZeroArgConstructorForGson() { diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest-test-config.js b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest-test-config.js index f64af82feb..eab98e8bd7 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest-test-config.js +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest-test-config.js @@ -1,3 +1,23 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ jsonObject = { "_countries": QPID.iterations( { "__ITERATING_VALUE": [ 0, 1 ] }, @@ -20,4 +40,4 @@ jsonObject = { ) }) -} \ No newline at end of file +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest.java index eb4063888b..55c1d4a7bd 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/JavaScriptConfigEvaluatorTest.java @@ -25,15 +25,16 @@ import static org.apache.commons.beanutils.PropertyUtils.getProperty; import java.util.List; import java.util.TreeMap; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; import com.google.gson.Gson; -public class JavaScriptConfigEvaluatorTest extends TestCase +public class JavaScriptConfigEvaluatorTest extends QpidTestCase { public void testEvaluateJavaScript() throws Exception { - String jsFilePath = getClass().getResource("JavaScriptConfigEvaluatorTest-test-config.js").toURI().getPath(); + String jsFilePath = TestFileUtils.createTempFileFromResource(this, "JavaScriptConfigEvaluatorTest-test-config.js").getAbsolutePath(); String rawConfig = new JavaScriptConfigEvaluator().evaluateJavaScript(jsFilePath); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/MessageProviderConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/MessageProviderConfigTest.java index a3b367a4b4..148c07b1ca 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/MessageProviderConfigTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/MessageProviderConfigTest.java @@ -21,13 +21,12 @@ package org.apache.qpid.disttest.controller.config; import java.util.HashMap; import java.util.Map; -import junit.framework.TestCase; - import org.apache.qpid.disttest.client.property.PropertyValue; import org.apache.qpid.disttest.client.property.SimplePropertyValue; import org.apache.qpid.disttest.message.CreateMessageProviderCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class MessageProviderConfigTest extends TestCase +public class MessageProviderConfigTest extends QpidTestCase { public void testCreateCommandsForMessageProvider() { diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ParticipantConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ParticipantConfigTest.java index f58cc628a4..b6efd68cbd 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ParticipantConfigTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ParticipantConfigTest.java @@ -32,7 +32,7 @@ public class ParticipantConfigTest extends QpidTestCase setTestSystemProperty(ParticipantConfig.DURATION_OVERRIDE_SYSTEM_PROPERTY, String.valueOf(overriddenDuration)); CreateParticpantCommand createParticipantCommand = mock(CreateParticpantCommand.class); - ParticipantConfig participantConfig = new ParticipantConfig("name", "destinationName", 1, 2, 5000) + ParticipantConfig participantConfig = new ParticipantConfig("name", "destinationName", false, 1, 2, 5000) { }; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ProducerConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ProducerConfigTest.java index b9e591f113..44fca4bb7c 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ProducerConfigTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/ProducerConfigTest.java @@ -22,11 +22,10 @@ package org.apache.qpid.disttest.controller.config; import javax.jms.DeliveryMode; import javax.jms.Message; -import junit.framework.TestCase; - import org.apache.qpid.disttest.message.CreateProducerCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class ProducerConfigTest extends TestCase +public class ProducerConfigTest extends QpidTestCase { public void testProducerHasZeroArgConstructorForGson() { diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/SessionConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/SessionConfigTest.java index 8775e4064d..02cdbb8fca 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/SessionConfigTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/SessionConfigTest.java @@ -29,14 +29,13 @@ import java.util.List; import javax.jms.Session; -import junit.framework.TestCase; - import org.apache.qpid.disttest.message.Command; import org.apache.qpid.disttest.message.CreateConsumerCommand; import org.apache.qpid.disttest.message.CreateProducerCommand; import org.apache.qpid.disttest.message.CreateSessionCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class SessionConfigTest extends TestCase +public class SessionConfigTest extends QpidTestCase { private static final String CONNECTION_NAME = "conn1"; private static final String SESSION = "session1"; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestConfigTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestConfigTest.java index 1212a57606..be7c7a7c8c 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestConfigTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestConfigTest.java @@ -26,12 +26,11 @@ import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; -import junit.framework.TestCase; - import org.apache.qpid.disttest.controller.CommandForClient; import org.apache.qpid.disttest.message.NoOpCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class TestConfigTest extends TestCase +public class TestConfigTest extends QpidTestCase { private static final QueueConfig[] EMPTY_QUEUES_ARRAY = new QueueConfig[0]; private static final String CLIENT1 = "client1"; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestInstanceTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestInstanceTest.java index 928fbe58cf..187b57c399 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestInstanceTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/controller/config/TestInstanceTest.java @@ -26,14 +26,13 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import junit.framework.TestCase; - import org.apache.qpid.disttest.controller.CommandForClient; import org.apache.qpid.disttest.message.CreateConsumerCommand; import org.apache.qpid.disttest.message.CreateProducerCommand; import org.apache.qpid.disttest.message.NoOpCommand; +import org.apache.qpid.test.utils.QpidTestCase; -public class TestInstanceTest extends TestCase +public class TestInstanceTest extends QpidTestCase { private static final String CLIENT_NAME = "CLIENT_NAME"; private static final int ITERATION_NUMBER = 0; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/db/ResultsDbWriterTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/db/ResultsDbWriterTest.java new file mode 100644 index 0000000000..abc6b44493 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/db/ResultsDbWriterTest.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.db; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; +import static org.apache.qpid.test.utils.TestFileUtils.createTestDirectory; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.Hashtable; +import java.util.TimeZone; + +import javax.naming.Context; +import javax.naming.NamingException; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.db.ResultsDbWriter.Clock; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.ResultsTestFixture; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.util.FileUtils; + +public class ResultsDbWriterTest extends QpidTestCase +{ + private static final long _dummyTimestamp = 1234; + + private File _tempDbDirectory; + private Clock _clock = mock(Clock.class); + private ResultsTestFixture _resultsTestFixture = new ResultsTestFixture(); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _tempDbDirectory = createTestDirectory(); + when(_clock.currentTimeMillis()).thenReturn(_dummyTimestamp); + } + + + @Override + protected void tearDown() throws Exception + { + try + { + FileUtils.deleteDirectory(_tempDbDirectory.getAbsolutePath()); + } + finally + { + super.tearDown(); + } + } + + + public void testWriteResults() throws Exception + { + Context context = getContext(); + ResultsForAllTests results = _resultsTestFixture.createResultsForAllTests(); + String runId = "myRunId"; + + ResultsDbWriter resultsDbWriter = new ResultsDbWriter(context, runId, _clock); + resultsDbWriter.createResultsTableIfNecessary(); + + resultsDbWriter.writeResults(results); + + ParticipantResult expectedResult = _resultsTestFixture.getFirstParticipantResult(results); + assertResultsAreInDb(context, expectedResult, runId); + } + + public void testDefaultRunId() throws Exception + { + TimeZone defaultTimeZone = TimeZone.getDefault(); + try + { + // set non-GMT timezone to make the test more rigorous. + TimeZone.setDefault(TimeZone.getTimeZone("GMT-05:00")); + ResultsDbWriter resultsDbWriter = new ResultsDbWriter(getContext(), null, _clock); + String runId = resultsDbWriter.getRunId(); + assertEquals( + "Default run id '" + runId + "' should correspond to dummy timestamp " + _clock.currentTimeMillis(), + "run 1970-01-01 00:00:01.234", + runId); + } + finally + { + TimeZone.setDefault(defaultTimeZone); + } + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private Context getContext() throws NamingException + { + Context context = mock(Context.class); + Hashtable environment = new Hashtable(); + + environment.put(ResultsDbWriter.DRIVER_NAME, "org.apache.derby.jdbc.EmbeddedDriver"); + environment.put(ResultsDbWriter.URL, "jdbc:derby:" + _tempDbDirectory + "perftestResultsDb;create=true"); + + when(context.getEnvironment()).thenReturn(environment); + return context; + } + + @SuppressWarnings("unchecked") + private void assertResultsAreInDb(Context context, ParticipantResult participantResult, String expectedRunId) throws Exception + { + String driverName = (String) context.getEnvironment().get(ResultsDbWriter.DRIVER_NAME); + Class driverClass = (Class) Class.forName(driverName); + driverClass.newInstance(); + String url = (String) context.getEnvironment().get(ResultsDbWriter.URL); + + Connection connection = DriverManager.getConnection(url); + Statement statement = connection.createStatement(); + ResultSet rs = statement.executeQuery( + "SELECT * FROM results WHERE testName='" + participantResult.getTestName() + + "' AND runId='" + expectedRunId + "'"); + + try + { + rs.next(); + assertEquals(participantResult.getTestName(), rs.getString(TEST_NAME.getDisplayName())); + assertEquals(participantResult.getIterationNumber(), rs.getInt(ITERATION_NUMBER.getDisplayName())); + assertEquals(participantResult.getParticipantName(), rs.getString(PARTICIPANT_NAME.getDisplayName())); + assertEquals(participantResult.getThroughput(), rs.getDouble(THROUGHPUT.getDisplayName())); + assertEquals(expectedRunId, rs.getString(ResultsDbWriter.RUN_ID)); + assertEquals(new Timestamp(_dummyTimestamp), rs.getTimestamp(ResultsDbWriter.INSERTED_TIMESTAMP)); + } + finally + { + connection.close(); + } + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/jms/JmsMessageAdaptorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/jms/JmsMessageAdaptorTest.java index ab0f52263b..d4f0cb1f22 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/jms/JmsMessageAdaptorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/jms/JmsMessageAdaptorTest.java @@ -18,12 +18,11 @@ */ package org.apache.qpid.disttest.jms; -import junit.framework.TestCase; - import org.apache.qpid.disttest.message.Command; import org.apache.qpid.disttest.message.CommandType; +import org.apache.qpid.test.utils.QpidTestCase; -public class JmsMessageAdaptorTest extends TestCase +public class JmsMessageAdaptorTest extends QpidTestCase { public void testCheckAllCommandTypes() diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/message/JsonHandlerTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/message/JsonHandlerTest.java index 4a56fff8fe..2e0c2e1ecd 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/message/JsonHandlerTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/message/JsonHandlerTest.java @@ -24,14 +24,13 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import junit.framework.TestCase; - import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.qpid.disttest.client.property.ListPropertyValue; import org.apache.qpid.disttest.client.property.PropertyValue; import org.apache.qpid.disttest.json.JsonHandler; +import org.apache.qpid.test.utils.QpidTestCase; -public class JsonHandlerTest extends TestCase +public class JsonHandlerTest extends QpidTestCase { private JsonHandler _jsonHandler = null; private SendChristmasCards _testCommand = null; diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java index 34727a7b8d..e9d444d59c 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/message/ParticipantResultTest.java @@ -18,7 +18,8 @@ */ package org.apache.qpid.disttest.message; -import static org.apache.qpid.disttest.message.ParticipantAttribute.*; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ACKNOWLEDGE_MODE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; import static org.apache.qpid.disttest.message.ParticipantAttribute.DELIVERY_MODE; import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE; @@ -30,23 +31,25 @@ import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONO import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC; import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; import static org.apache.qpid.disttest.message.ParticipantAttribute.PRIORITY; import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_INTERVAL; import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_START_DELAY; import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TAKEN; import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TO_LIVE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_CONSUMERS; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_PRODUCERS; import java.util.Date; import javax.jms.DeliveryMode; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class ParticipantResultTest extends TestCase +public class ParticipantResultTest extends QpidTestCase { public void testSharedParticipantResultAttributes() throws Exception diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/ResultsTestFixture.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/ResultsTestFixture.java new file mode 100644 index 0000000000..1edef031bf --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/ResultsTestFixture.java @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.results; + +import static org.apache.qpid.disttest.message.ParticipantAttribute.ACKNOWLEDGE_MODE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.AVERAGE_LATENCY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.DELIVERY_MODE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSING_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONOUS_CONSUMER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC; +import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; +import static org.apache.qpid.disttest.message.ParticipantAttribute.LATENCY_STANDARD_DEVIATION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MAX_LATENCY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MESSAGE_THROUGHPUT; +import static org.apache.qpid.disttest.message.ParticipantAttribute.MIN_LATENCY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRIORITY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_INTERVAL; +import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_START_DELAY; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; +import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TAKEN; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TO_LIVE; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_CONSUMERS; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_PRODUCERS; +import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_PAYLOAD_PROCESSED; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.controller.TestResult; +import org.apache.qpid.disttest.message.ParticipantAttribute; +import org.apache.qpid.disttest.message.ParticipantResult; +import org.apache.qpid.disttest.results.aggregation.ITestResult; + +public class ResultsTestFixture +{ + public static final double THROUGHPUT_VALUE = 2048.49; + + private static final String TEST1 = "TEST1"; + private static final String PARTICIPANT = "PARTICIPANT"; + private static final String CONFIGURED_CLIENT1 = "CONFIGURED_CLIENT1"; + + public ResultsForAllTests createResultsForAllTests() + { + ParticipantResult participantResult = mock(ParticipantResult.class); + Map participantAttributes = getParticipantAttributes(); + + when(participantResult.getAttributes()).thenReturn(participantAttributes); + when(participantResult.getParticipantName()).thenReturn(PARTICIPANT); + when(participantResult.getTestName()).thenReturn(TEST1); + when(participantResult.getIterationNumber()).thenReturn(0); + when(participantResult.getThroughput()).thenReturn(THROUGHPUT_VALUE); + + TestResult testResult = new TestResult(TEST1); + testResult.addParticipantResult(participantResult); + + ResultsForAllTests resultsForAllTests = new ResultsForAllTests(); + resultsForAllTests.add(testResult); + return resultsForAllTests; + } + + private Map getParticipantAttributes() + { + Map participantAttributes = new HashMap(); + + participantAttributes.put(TEST_NAME, TEST1); + participantAttributes.put(ITERATION_NUMBER, 0); + participantAttributes.put(CONFIGURED_CLIENT_NAME, CONFIGURED_CLIENT1); + participantAttributes.put(PARTICIPANT_NAME, PARTICIPANT); + participantAttributes.put(NUMBER_OF_MESSAGES_PROCESSED, 2); + participantAttributes.put(PAYLOAD_SIZE, 1); + participantAttributes.put(PRIORITY, 2); + participantAttributes.put(TIME_TO_LIVE, 3); + participantAttributes.put(ACKNOWLEDGE_MODE, 4); + participantAttributes.put(DELIVERY_MODE, 5); + participantAttributes.put(BATCH_SIZE, 6); + participantAttributes.put(MAXIMUM_DURATION, 7); + participantAttributes.put(PRODUCER_START_DELAY, 8); + participantAttributes.put(PRODUCER_INTERVAL, 9); + participantAttributes.put(IS_TOPIC, true); + participantAttributes.put(IS_DURABLE_SUBSCRIPTION, false); + participantAttributes.put(IS_BROWSING_SUBSCRIPTION, true); + participantAttributes.put(IS_SELECTOR, false); + participantAttributes.put(IS_NO_LOCAL, true); + participantAttributes.put(IS_SYNCHRONOUS_CONSUMER, false); + participantAttributes.put(TOTAL_NUMBER_OF_CONSUMERS, 1); + participantAttributes.put(TOTAL_NUMBER_OF_PRODUCERS, 2); + participantAttributes.put(TOTAL_PAYLOAD_PROCESSED, 1024); + participantAttributes.put(THROUGHPUT, THROUGHPUT_VALUE); + participantAttributes.put(TIME_TAKEN, 1000); + participantAttributes.put(ERROR_MESSAGE, "error"); + participantAttributes.put(MIN_LATENCY, 2l); + participantAttributes.put(MAX_LATENCY, 9l); + participantAttributes.put(AVERAGE_LATENCY, 4.6f); + participantAttributes.put(LATENCY_STANDARD_DEVIATION, 2.0f); + participantAttributes.put(MESSAGE_THROUGHPUT, 2); + return participantAttributes; + } + + public ParticipantResult getFirstParticipantResult(ResultsForAllTests results) + { + List testResults = results.getTestResults(); + ITestResult testResult = testResults.iterator().next(); + List participantResults = testResult.getParticipantResults(); + return participantResults.iterator().next(); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/AggregatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/AggregatorTest.java index 393837b4d5..011eb4e68b 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/AggregatorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/AggregatorTest.java @@ -24,11 +24,10 @@ import static org.mockito.Mockito.when; import java.util.Arrays; -import junit.framework.TestCase; - import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.test.utils.QpidTestCase; -public class AggregatorTest extends TestCase +public class AggregatorTest extends QpidTestCase { private Aggregator _aggregator = new Aggregator(); private TestResultAggregator _testResultAggregator = mock(TestResultAggregator.class); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregatorTest.java index 72743be1d1..41da1edb33 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregatorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/ParticipantResultAggregatorTest.java @@ -24,11 +24,9 @@ import java.util.Date; import javax.jms.Session; import org.apache.qpid.disttest.message.ParticipantResult; -import org.apache.qpid.disttest.results.aggregation.ParticipantResultAggregator; +import org.apache.qpid.test.utils.QpidTestCase; -import junit.framework.TestCase; - -public class ParticipantResultAggregatorTest extends TestCase +public class ParticipantResultAggregatorTest extends QpidTestCase { private ParticipantResultAggregator _aggregator = new ParticipantResultAggregator(ParticipantResult.class, AGGREGATED_RESULT_NAME); @@ -39,15 +37,19 @@ public class ParticipantResultAggregatorTest extends TestCase private static final long PARTICIPANT1_STARTDATE = 50; private static final long PARTICIPANT1_ENDDATE = 20000; private static final long PARTICIPANT1_TOTAL_PROCESSED = 1024; + private static final int PARTICIPANT1_NUMBER_OF_MESSAGES_PROCESSED = 20000; private static final long PARTICIPANT2_STARTDATE = 100; private static final long PARTICIPANT2_ENDDATE = 21000; private static final long PARTICIPANT2_TOTAL_PROCESSED = 2048; + private static final int PARTICIPANT2_NUMBER_OF_MESSAGES_PROCESSED = 950; private static final long OVERALL_PROCESSED = PARTICIPANT1_TOTAL_PROCESSED + PARTICIPANT2_TOTAL_PROCESSED; private static final double OVERALL_TIMETAKEN = PARTICIPANT2_ENDDATE - PARTICIPANT1_STARTDATE; + private static final long OVERALL_NUMBER_OF_MESSAGES_PROCESSED = PARTICIPANT1_NUMBER_OF_MESSAGES_PROCESSED + PARTICIPANT2_NUMBER_OF_MESSAGES_PROCESSED; private static final double EXPECTED_AGGREGATED_ALL_THROUGHPUT = ((OVERALL_PROCESSED)/1024)/((OVERALL_TIMETAKEN)/1000); + private static final int EXPECTED_AGGREGATED_MESSAGE_THROUGHPUT = (int)(OVERALL_NUMBER_OF_MESSAGES_PROCESSED * 1000.0d/OVERALL_TIMETAKEN); public void testStartAndEndDateForOneParticipantResult() { @@ -128,6 +130,26 @@ public class ParticipantResultAggregatorTest extends TestCase assertEquals(EXPECTED_AGGREGATED_ALL_THROUGHPUT, aggregratedResult.getThroughput(), 0.1); } + public void testComputeMessageThroughput() + { + ParticipantResult result1 = new ParticipantResult(); + result1.setStartDate(new Date(PARTICIPANT1_STARTDATE)); + result1.setEndDate(new Date(PARTICIPANT1_ENDDATE)); + result1.setNumberOfMessagesProcessed(PARTICIPANT1_NUMBER_OF_MESSAGES_PROCESSED); + + ParticipantResult result2 = new ParticipantResult(); + result2.setStartDate(new Date(PARTICIPANT2_STARTDATE)); + result2.setEndDate(new Date(PARTICIPANT2_ENDDATE)); + result2.setNumberOfMessagesProcessed(PARTICIPANT2_NUMBER_OF_MESSAGES_PROCESSED); + + _aggregator.aggregate(result1); + _aggregator.aggregate(result2); + + ParticipantResult aggregratedResult = _aggregator.getAggregatedResult(); + assertEquals(EXPECTED_AGGREGATED_MESSAGE_THROUGHPUT, aggregratedResult.getMessageThroughput()); + + } + public void testConstantTestNameAndIterationNumberRolledUp() throws Exception { ParticipantResult result1 = new ParticipantResult(); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/SeriesStatisticsTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/SeriesStatisticsTest.java index ec8da8418f..7417dddc4f 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/SeriesStatisticsTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/SeriesStatisticsTest.java @@ -23,9 +23,9 @@ package org.apache.qpid.disttest.results.aggregation; import java.util.Arrays; import java.util.Collection; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class SeriesStatisticsTest extends TestCase +public class SeriesStatisticsTest extends QpidTestCase { public static Collection SERIES = Arrays.asList(new Long[] { 2l, 4l, 4l, 4l, 5l, 5l, 7l, 9l, 5l }); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java index 9c00e7cf1c..b254a0e3bf 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/aggregation/TestResultAggregatorTest.java @@ -18,29 +18,30 @@ */ package org.apache.qpid.disttest.results.aggregation; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; import java.util.Date; import java.util.List; -import junit.framework.TestCase; - +import org.apache.qpid.disttest.controller.ResultsForAllTests; import org.apache.qpid.disttest.controller.TestResult; import org.apache.qpid.disttest.message.ConsumerParticipantResult; import org.apache.qpid.disttest.message.ParticipantResult; import org.apache.qpid.disttest.message.ProducerParticipantResult; +import org.apache.qpid.test.utils.QpidTestCase; -public class TestResultAggregatorTest extends TestCase +public class TestResultAggregatorTest extends QpidTestCase { - private static final String TEST1_NAME = "TEST1_NAME"; private static final int TEST1_ITERATION_NUMBER = 1; - private static final String CONSUMER_PARTICIPANT_NAME1 = "CONSUMER_PARTICIPANT_NAME1"; private static final String CONSUMER_PARTICIPANT_NAME2 = "CONSUMER_PARTICIPANT_NAME2"; private static final String PRODUCER_PARTICIPANT_NAME = "PRODUCER_PARTICIPANT_NAME"; - private static final long CONSUMER1_STARTDATE = 50; private static final long CONSUMER1_ENDDATE = 20000; @@ -64,6 +65,33 @@ public class TestResultAggregatorTest extends TestCase private TestResultAggregator _aggregator = new TestResultAggregator(); + public void testAggregateTestResults() + { + ResultsForAllTests resultsForAllTests1 = mock(ResultsForAllTests.class); + ResultsForAllTests resultsForAllTests2 = mock(ResultsForAllTests.class); + + ResultsForAllTests summaryResult1 = mock(ResultsForAllTests.class); + ResultsForAllTests summaryResult2 = mock(ResultsForAllTests.class); + + when(resultsForAllTests1.getAllParticipantsResult()).thenReturn(summaryResult1); + when(resultsForAllTests2.getAllParticipantsResult()).thenReturn(summaryResult2); + + ITestResult testResult1 = mock(ITestResult.class); + ITestResult testResult2 = mock(ITestResult.class); + + when(summaryResult1.getTestResults()).thenReturn(Arrays.asList(testResult1)); + when(summaryResult2.getTestResults()).thenReturn(Arrays.asList(testResult2)); + + ResultsForAllTests actualSummaryResults = _aggregator.aggregateTestResults(Arrays.asList( + resultsForAllTests1, + resultsForAllTests2)); + + assertEquals( + "Summary results should contain the all the 'all participants' test results", + Arrays.asList(testResult1, testResult2), + actualSummaryResults.getTestResults()); + } + public void testAggregateResultsForTwoConsumerAndOneProducer() throws Exception { TestResult originalTestResult = createResultsFromTest(); @@ -141,6 +169,10 @@ public class TestResultAggregatorTest extends TestCase aggregatedTestResult.getAllParticipantResult(), TEST1_NAME, TEST1_ITERATION_NUMBER, BATCH_SIZE, NUMBER_OF_MESSAGES_CONSUMED_IN_TOTAL, 2, 1); + + int expectedThroughtput = (int)Math.round(NUMBER_OF_MESSAGES_PRODUCED * 1000.0d /(CONSUMER2_ENDDATE - PRODUCER_STARTDATE)); + ParticipantResult result = aggregatedTestResult.getAllParticipantResult(); + assertEquals("Unexpected message throughtput", expectedThroughtput, result.getMessageThroughput()); } private void assertLatencyAggregatedResults(ParticipantResult allConsumerParticipantResult) @@ -197,4 +229,5 @@ public class TestResultAggregatorTest extends TestCase participantResult.setEndDate(new Date(end)); participantResult.setBatchSize(batchSize); } + } diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java deleted file mode 100644 index 565f59d25b..0000000000 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormaterTest.java +++ /dev/null @@ -1,146 +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.disttest.results.formatting; - -import static org.apache.qpid.disttest.message.ParticipantAttribute.BATCH_SIZE; -import static org.apache.qpid.disttest.message.ParticipantAttribute.CONFIGURED_CLIENT_NAME; -import static org.apache.qpid.disttest.message.ParticipantAttribute.*; -import static org.apache.qpid.disttest.message.ParticipantAttribute.ERROR_MESSAGE; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_BROWSING_SUBSCRIPTION; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_DURABLE_SUBSCRIPTION; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_NO_LOCAL; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SELECTOR; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_SYNCHRONOUS_CONSUMER; -import static org.apache.qpid.disttest.message.ParticipantAttribute.IS_TOPIC; -import static org.apache.qpid.disttest.message.ParticipantAttribute.ITERATION_NUMBER; -import static org.apache.qpid.disttest.message.ParticipantAttribute.MAXIMUM_DURATION; -import static org.apache.qpid.disttest.message.ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PARTICIPANT_NAME; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PAYLOAD_SIZE; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PRIORITY; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_INTERVAL; -import static org.apache.qpid.disttest.message.ParticipantAttribute.PRODUCER_START_DELAY; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TEST_NAME; -import static org.apache.qpid.disttest.message.ParticipantAttribute.THROUGHPUT; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TAKEN; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TIME_TO_LIVE; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_CONSUMERS; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_NUMBER_OF_PRODUCERS; -import static org.apache.qpid.disttest.message.ParticipantAttribute.TOTAL_PAYLOAD_PROCESSED; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; - -import junit.framework.TestCase; - -import org.apache.qpid.disttest.controller.ResultsForAllTests; -import org.apache.qpid.disttest.controller.TestResult; -import org.apache.qpid.disttest.message.ParticipantAttribute; -import org.apache.qpid.disttest.message.ParticipantResult; - -public class CSVFormaterTest extends TestCase -{ - private static final String TEST1 = "TEST1"; - private static final String PARTICIPANT = "PARTICIPANT"; - private static final String CONFIGURED_CLIENT1 = "CONFIGURED_CLIENT1"; - - private CSVFormater _formatter = new CSVFormater(); - - public void testResultsFileWithWithOneRow() throws Exception - { - ParticipantResult participantResult = mock(ParticipantResult.class); - Map participantAttributes = getParticipantAttributes(); - - when(participantResult.getAttributes()).thenReturn(participantAttributes); - when(participantResult.getParticipantName()).thenReturn(PARTICIPANT); - - TestResult testResult = new TestResult(TEST1); - testResult.addParticipantResult(participantResult); - - ResultsForAllTests resultsForAllTests = new ResultsForAllTests(); - resultsForAllTests.add(testResult); - - String output = _formatter.format(resultsForAllTests); - - String expectedOutput = readCsvOutputFileAsString("expectedOutput.csv"); - - assertEquals(expectedOutput, output); - } - - private Map getParticipantAttributes() - { - Map participantAttributes = new HashMap(); - - participantAttributes.put(TEST_NAME, TEST1); - participantAttributes.put(ITERATION_NUMBER, 0); - participantAttributes.put(CONFIGURED_CLIENT_NAME, CONFIGURED_CLIENT1); - participantAttributes.put(PARTICIPANT_NAME, PARTICIPANT); - participantAttributes.put(NUMBER_OF_MESSAGES_PROCESSED, 0); - participantAttributes.put(PAYLOAD_SIZE, 1); - participantAttributes.put(PRIORITY, 2); - participantAttributes.put(TIME_TO_LIVE, 3); - participantAttributes.put(ACKNOWLEDGE_MODE, 4); - participantAttributes.put(DELIVERY_MODE, 5); - participantAttributes.put(BATCH_SIZE, 6); - participantAttributes.put(MAXIMUM_DURATION, 7); - participantAttributes.put(PRODUCER_START_DELAY, 8); - participantAttributes.put(PRODUCER_INTERVAL, 9); - participantAttributes.put(IS_TOPIC, true); - participantAttributes.put(IS_DURABLE_SUBSCRIPTION, false); - participantAttributes.put(IS_BROWSING_SUBSCRIPTION, true); - participantAttributes.put(IS_SELECTOR, false); - participantAttributes.put(IS_NO_LOCAL, true); - participantAttributes.put(IS_SYNCHRONOUS_CONSUMER, false); - participantAttributes.put(TOTAL_NUMBER_OF_CONSUMERS, 1); - participantAttributes.put(TOTAL_NUMBER_OF_PRODUCERS, 2); - participantAttributes.put(TOTAL_PAYLOAD_PROCESSED, 1024); - participantAttributes.put(THROUGHPUT, 2048); - participantAttributes.put(TIME_TAKEN, 1000); - participantAttributes.put(ERROR_MESSAGE, "error"); - participantAttributes.put(MIN_LATENCY, 2l); - participantAttributes.put(MAX_LATENCY, 9l); - participantAttributes.put(AVERAGE_LATENCY, 5.0f); - participantAttributes.put(LATENCY_STANDARD_DEVIATION, 2.0f); - return participantAttributes; - } - - private String readCsvOutputFileAsString(String filename) throws Exception - { - InputStream is = getClass().getResourceAsStream(filename); - assertNotNull(is); - - StringBuilder output = new StringBuilder(); - - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - String line = null; - while((line = br.readLine()) != null) - { - output.append(line); - output.append("\n"); - } - - return output.toString(); - } - -} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormatterTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormatterTest.java new file mode 100644 index 0000000000..bbf73b23d2 --- /dev/null +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVFormatterTest.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.results.formatting; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.apache.qpid.disttest.controller.ResultsForAllTests; +import org.apache.qpid.disttest.results.ResultsTestFixture; +import org.apache.qpid.test.utils.QpidTestCase; + +public class CSVFormatterTest extends QpidTestCase +{ + private CSVFormatter _formatter = new CSVFormatter(); + + public void testResultsFileWithWithOneRow() throws Exception + { + ResultsTestFixture resultsTestFixture = new ResultsTestFixture(); + ResultsForAllTests resultsForAllTests = resultsTestFixture.createResultsForAllTests(); + + String output = _formatter.format(resultsForAllTests); + + String expectedOutput = readCsvOutputFileAsString("expectedOutput.csv"); + + assertEquals(expectedOutput, output); + } + + private String readCsvOutputFileAsString(String filename) throws Exception + { + InputStream is = getClass().getResourceAsStream(filename); + assertNotNull(is); + + StringBuilder output = new StringBuilder(); + + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line = null; + while((line = br.readLine()) != null) + { + output.append(line); + output.append("\n"); + } + + return output.toString(); + } +} diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparatorTest.java b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparatorTest.java index 6cec4b5245..ed109a2e27 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparatorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/CSVOrderParticipantResultComparatorTest.java @@ -19,15 +19,13 @@ package org.apache.qpid.disttest.results.formatting; -import junit.framework.TestCase; - import org.apache.qpid.disttest.message.ConsumerParticipantResult; import org.apache.qpid.disttest.message.ParticipantResult; import org.apache.qpid.disttest.message.ProducerParticipantResult; import org.apache.qpid.disttest.results.aggregation.TestResultAggregator; -import org.apache.qpid.disttest.results.formatting.CSVOrderParticipantResultComparator; +import org.apache.qpid.test.utils.QpidTestCase; -public class CSVOrderParticipantResultComparatorTest extends TestCase +public class CSVOrderParticipantResultComparatorTest extends QpidTestCase { CSVOrderParticipantResultComparator _comparator = new CSVOrderParticipantResultComparator(); diff --git a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv index ada2303d46..02ea67d56d 100644 --- a/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv +++ b/java/perftests/src/test/java/org/apache/qpid/disttest/results/formatting/expectedOutput.csv @@ -1,2 +1,2 @@ -testName,iterationNumber,clientName,participantName,numberOfMessages,payloadSizeB,priority,timeToLiveMs,acknowledgeMode,deliveryMode,batchSize,maximumDurationMs,producerStartDelayMs,producerIntervalMs,isTopic,isDurableSubscription,isBrowsingSubscription,isSelector,isNoLocal,isSynchronousConsumer,totalNumberOfConsumers,totalNumberOfProducers,totalPayloadProcessedB,throughputKbPerS,timeTakenMs,errorMessage,minLatency,maxLatency,averageLatency,latencyStandardDeviation -TEST1,0,CONFIGURED_CLIENT1,PARTICIPANT,0,1,2,3,4,5,6,7,8,9,true,false,true,false,true,false,1,2,1024,2048,1000,error,2,9,5.0,2.0 +testName,iterationNumber,throughputKbPerS,averageLatency,clientName,participantName,numberOfMessages,payloadSizeB,priority,timeToLiveMs,acknowledgeMode,deliveryMode,batchSize,maximumDurationMs,producerStartDelayMs,producerIntervalMs,isTopic,isDurableSubscription,isBrowsingSubscription,isSelector,isNoLocal,isSynchronousConsumer,totalNumberOfConsumers,totalNumberOfProducers,totalPayloadProcessedB,timeTakenMs,errorMessage,minLatency,maxLatency,latencyStandardDeviation,throughputMessagesPerS +TEST1,0,2048,5,CONFIGURED_CLIENT1,PARTICIPANT,2,1,2,3,4,5,6,7,8,9,true,false,true,false,true,false,1,2,1024,1000,error,2,9,2.0,2 diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/QpidQueueCreatorTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/QpidQueueCreatorTest.java index 784e43469e..59396d46c0 100644 --- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/QpidQueueCreatorTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/QpidQueueCreatorTest.java @@ -29,7 +29,6 @@ import javax.jms.Session; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQSession; -import org.apache.qpid.disttest.DistributedTestException; import org.apache.qpid.disttest.controller.config.QueueConfig; import org.apache.qpid.disttest.jms.QpidQueueCreator; @@ -37,6 +36,9 @@ public class QpidQueueCreatorTest extends DistributedTestSystemTestBase { private static final Map EMPTY_ATTRIBUTES = Collections.emptyMap(); + private static final boolean QUEUE_DURABILITY = true; + + private Connection _connection; private QpidQueueCreator _creator; private Session _session; private List _configs; @@ -46,20 +48,20 @@ public class QpidQueueCreatorTest extends DistributedTestSystemTestBase public void setUp() throws Exception { super.setUp(); - Connection connection = getConnection(); - _session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + _connection = getConnection(); + _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); _creator = new QpidQueueCreator(); _configs = new ArrayList(); - _queueName = "direct://amq.direct//" + getTestQueueName(); + _queueName = "direct://amq.direct//" + getTestQueueName() + "?durable='" + QUEUE_DURABILITY + "'"; } public void testCreateQueueWithoutAttributes() throws Exception { - _configs.add(new QueueConfig(_queueName, true, EMPTY_ATTRIBUTES)); + _configs.add(new QueueConfig(_queueName, QUEUE_DURABILITY, EMPTY_ATTRIBUTES)); assertQueueBound(_queueName, false); - _creator.createQueues(_session, _configs); + _creator.createQueues(_connection, _session, _configs); assertQueueBound(_queueName, true); } @@ -68,46 +70,28 @@ public class QpidQueueCreatorTest extends DistributedTestSystemTestBase { Map attributes = new HashMap(); attributes.put("x-qpid-priorities", Integer.valueOf(5)); - _configs.add(new QueueConfig(_queueName, true, attributes)); + _configs.add(new QueueConfig(_queueName, QUEUE_DURABILITY, attributes)); assertQueueBound(_queueName, false); - _creator.createQueues(_session, _configs); + _creator.createQueues(_connection, _session, _configs); assertQueueBound(_queueName, true); } public void testDeleteQueues() throws Exception { - _configs.add(new QueueConfig(_queueName, true, EMPTY_ATTRIBUTES)); + _configs.add(new QueueConfig(_queueName, QUEUE_DURABILITY, EMPTY_ATTRIBUTES)); assertQueueBound(_queueName, false); - _creator.createQueues(_session, _configs); + _creator.createQueues(_connection, _session, _configs); assertQueueBound(_queueName, true); - _creator.deleteQueues(_session, _configs); + _creator.deleteQueues(_connection, _session, _configs); assertQueueBound(_queueName, false); } - public void testDeleteQueueThatDoesNotExist() throws Exception - { - String queueThatDoesNotExist = _queueName; - List configs = new ArrayList(); - Map attributes = Collections.emptyMap(); - configs.add(new QueueConfig(queueThatDoesNotExist, true, attributes)); - - try - { - _creator.deleteQueues(_session, configs); - fail("Exception not thrown"); - } - catch (DistributedTestException e) - { - // PASS - } - } - private void assertQueueBound(String queueName, boolean isBound) throws Exception { AMQDestination destination = (AMQDestination)_session.createQueue(queueName); diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/SystemTestConstants.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/SystemTestConstants.java index 808b428bc9..b06ab0c735 100644 --- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/SystemTestConstants.java +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/SystemTestConstants.java @@ -21,8 +21,8 @@ package org.apache.qpid.systest.disttest; public abstract class SystemTestConstants { - public static final long REGISTRATION_TIMEOUT = 5000; - public static final long COMMAND_RESPONSE_TIMEOUT = 10000; - public static final long TEST_RESULT_TIMEOUT = 5000; + public static final long REGISTRATION_TIMEOUT = 20000; + public static final long COMMAND_RESPONSE_TIMEOUT = 30000; + public static final long TEST_RESULT_TIMEOUT = 20000; } diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java index 7e58e1b5b1..a0c2a4b342 100644 --- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/EndToEndTest.java @@ -20,7 +20,9 @@ package org.apache.qpid.systest.disttest.endtoend; import static org.apache.qpid.disttest.AbstractRunner.JNDI_CONFIG_PROP; import static org.apache.qpid.disttest.ControllerRunner.OUTPUT_DIR_PROP; +import static org.apache.qpid.disttest.ControllerRunner.RUN_ID; import static org.apache.qpid.disttest.ControllerRunner.TEST_CONFIG_PROP; +import static org.apache.qpid.disttest.ControllerRunner.WRITE_TO_DB; import java.io.File; import java.io.IOException; @@ -36,6 +38,7 @@ public class EndToEndTest extends QpidBrokerTestCase private ControllerRunner _runner; private static final String TEST_CONFIG = "perftests/src/test/java/org/apache/qpid/systest/disttest/endtoend/endtoend.json"; private static final String JNDI_CONFIG_FILE = "perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties"; + private static final String RUN1 = "run1"; public void testRunner() throws Exception { @@ -44,6 +47,8 @@ public class EndToEndTest extends QpidBrokerTestCase final String[] args = new String[] {TEST_CONFIG_PROP + "=" + TEST_CONFIG, JNDI_CONFIG_PROP + "=" + JNDI_CONFIG_FILE, + WRITE_TO_DB + "=true", + RUN_ID + "=" + RUN1, OUTPUT_DIR_PROP + "=" + csvOutputDir.getAbsolutePath()}; _runner = new ControllerRunner(); _runner.parseArgumentsIntoConfig(args); @@ -76,10 +81,10 @@ public class EndToEndTest extends QpidBrokerTestCase String[] cells = csvLine.split(",", DONT_STRIP_EMPTY_LAST_FIELD_FLAG); // All attributes become cells in the CSV, so this will be true assertEquals("Unexpected number of cells in CSV line " + csvLine, ParticipantAttribute.values().length, cells.length); - assertEquals("Unexpected test name in CSV line " + csvLine, testName, cells[0]); - assertEquals("Unexpected client name in CSV line " + csvLine, clientName, cells[2]); - assertEquals("Unexpected participant name in CSV line " + csvLine, participantName, cells[3]); - assertEquals("Unexpected number of messages processed in CSV line " + csvLine, String.valueOf(expectedNumberOfMessagesProcessed), cells[4]); + assertEquals("Unexpected test name in CSV line " + csvLine, testName, cells[ParticipantAttribute.TEST_NAME.ordinal()]); + assertEquals("Unexpected client name in CSV line " + csvLine, clientName, cells[ParticipantAttribute.CONFIGURED_CLIENT_NAME.ordinal()]); + assertEquals("Unexpected participant name in CSV line " + csvLine, participantName, cells[ParticipantAttribute.PARTICIPANT_NAME.ordinal()]); + assertEquals("Unexpected number of messages processed in CSV line " + csvLine, String.valueOf(expectedNumberOfMessagesProcessed), cells[ParticipantAttribute.NUMBER_OF_MESSAGES_PROCESSED.ordinal()]); } diff --git a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties index b5d053227c..149e632048 100644 --- a/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties +++ b/java/perftests/src/test/java/org/apache/qpid/systest/disttest/perftests.systests.properties @@ -24,3 +24,6 @@ java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextF connectionfactory.connectionfactory = amqp://guest:guest@clientid/test?brokerlist='tcp://localhost:15672' destination.controllerqueue = direct://amq.direct//controllerqueue + +jdbcDriverClass=org.apache.derby.jdbc.EmbeddedDriver +jdbcUrl=jdbc:derby:/tmp/tempDbDirectory/perftestResultsDb;create=true diff --git a/java/perftests/visualisation-jfc/build.xml b/java/perftests/visualisation-jfc/build.xml index 02c9f5dcbd..04deb39d36 100644 --- a/java/perftests/visualisation-jfc/build.xml +++ b/java/perftests/visualisation-jfc/build.xml @@ -17,8 +17,8 @@ - under the License. --> - - + + diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java index ed09f4a77e..5a77f22148 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartType.java @@ -21,5 +21,5 @@ package org.apache.qpid.disttest.charting; public enum ChartType { - LINE, LINE3D, BAR, BAR3D, XYLINE, STATISTICAL_BAR + LINE, LINE3D, BAR, BAR3D, XYLINE, TIMELINE, STATISTICAL_BAR } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java index e00859855e..91eafe324b 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/ChartingUtil.java @@ -30,7 +30,8 @@ import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilder; import org.apache.qpid.disttest.charting.chartbuilder.ChartBuilderFactory; import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator; -import org.apache.qpid.disttest.charting.seriesbuilder.JdbcCsvSeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.JdbcSeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.JdbcUrlGenerator; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; import org.apache.qpid.disttest.charting.writer.ChartWriter; import org.jfree.chart.JFreeChart; @@ -44,24 +45,46 @@ import org.slf4j.LoggerFactory; * The following arguments are understood: *

*
    - *
  1. chart-defs=directory contain chartdef file(s)
  2. - *
  3. output-dir=directory in which to produce the PNGs
  4. + *
  5. {@link #OUTPUT_DIR_PROP}
  6. + *
  7. {@link #CHART_DEFINITIONS_PROP}
  8. + *
  9. {@link #SUMMARY_TITLE_PROP}
  10. + *
  11. {@link #JDBC_DRIVER_NAME_PROP}
  12. + *
  13. {@link #JDBC_URL_PROP}
  14. *
+ * Default values are indicated by the similarly named constants in this class. */ public class ChartingUtil { private static final Logger LOGGER = LoggerFactory.getLogger(ChartingUtil.class); + /** directory in which to produce the PNGs */ public static final String OUTPUT_DIR_PROP = "outputdir"; public static final String OUTPUT_DIR_DEFAULT = "."; + /** the path to the directory containing the chart definition files */ public static final String CHART_DEFINITIONS_PROP = "chart-defs"; public static final String CHART_DEFINITIONS_DEFAULT = "."; + public static final String SUMMARY_TITLE_PROP = "summary-title"; + public static final String SUMMARY_TITLE_DEFAULT = "Performance Charts"; + + /** the class name of the JDBC driver to use for reading the chart data */ + public static final String JDBC_DRIVER_NAME_PROP = "jdbcDriverClass"; + public static final String JDBC_DRIVER_NAME_DEFAULT = JdbcUrlGenerator.DEFAULT_JDBC_DRIVER_NAME; + + /** the JDBC URL of the data to be charted */ + public static final String JDBC_URL_PROP = "jdbcUrl"; + public static final String JDBC_URL_DEFAULT = null; + + private Map _cliOptions = new HashMap(); + { _cliOptions.put(OUTPUT_DIR_PROP, OUTPUT_DIR_DEFAULT); _cliOptions.put(CHART_DEFINITIONS_PROP, CHART_DEFINITIONS_DEFAULT); + _cliOptions.put(SUMMARY_TITLE_PROP, SUMMARY_TITLE_DEFAULT); + _cliOptions.put(JDBC_DRIVER_NAME_PROP, JDBC_DRIVER_NAME_DEFAULT); + _cliOptions.put(JDBC_URL_PROP, JDBC_URL_DEFAULT); } public static void main(String[] args) throws Exception @@ -82,26 +105,38 @@ public class ChartingUtil private void produceAllCharts() { - final String chartingDefsDir = _cliOptions.get(CHART_DEFINITIONS_PROP); - final File chartDirectory = new File(_cliOptions.get(OUTPUT_DIR_PROP)); - LOGGER.info("Chart chartdef directory/file: {} output directory : {}", chartingDefsDir, chartDirectory); - - List definitions = loadChartDefinitions(chartingDefsDir); - - LOGGER.info("There are {} chart(s) to produce", definitions.size()); final ChartWriter writer = new ChartWriter(); - writer.setOutputDirectory(chartDirectory); + writer.setOutputDirectory(new File(_cliOptions.get(OUTPUT_DIR_PROP))); + + SeriesBuilder seriesBuilder = new JdbcSeriesBuilder( + _cliOptions.get(JDBC_DRIVER_NAME_PROP), + _cliOptions.get(JDBC_URL_PROP)); - final SeriesBuilder seriesBuilder = new JdbcCsvSeriesBuilder(); - for (ChartingDefinition chartingDefinition : definitions) + for (ChartingDefinition chartingDefinition : loadChartDefinitions()) { - ChartBuilder chartBuilder = ChartBuilderFactory.createChartBuilder(chartingDefinition.getChartType(), seriesBuilder); + ChartBuilder chartBuilder = ChartBuilderFactory.createChartBuilder( + chartingDefinition.getChartType(), + seriesBuilder); + JFreeChart chart = chartBuilder.buildChart(chartingDefinition); - writer.writeChartToFileSystem(chart, chartingDefinition.getChartStemName()); + writer.writeChartToFileSystem(chart, chartingDefinition); } - writer.writeHtmlSummaryToFileSystem(); + final String summaryChartTitle = _cliOptions.get(SUMMARY_TITLE_PROP); + writer.writeHtmlSummaryToFileSystem(summaryChartTitle); + } + + private List loadChartDefinitions() + { + final String chartingDefsDir = _cliOptions.get(CHART_DEFINITIONS_PROP); + + LOGGER.info("Chart chartdef directory/file: {}", chartingDefsDir); + + List definitions = loadChartDefinitions(chartingDefsDir); + + LOGGER.info("There are {} chart(s) to produce", definitions.size()); + return definitions; } private List loadChartDefinitions(String chartingDefsDir) diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java index 491bb1c67d..b10fd477ed 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChart3DBuilder.java @@ -36,7 +36,7 @@ public class BarChart3DBuilder extends CategoryDataSetBasedChartBuilder } @Override - public JFreeChart createChartImpl(String title, String xAxisTitle, + protected JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) { diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java index b5c6a38067..7705ef5d3a 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BarChartBuilder.java @@ -35,7 +35,7 @@ public class BarChartBuilder extends CategoryDataSetBasedChartBuilder } @Override - public JFreeChart createChartImpl(String title, String xAxisTitle, + protected JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) { diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java index def87f5840..9cadf0ec3c 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilder.java @@ -23,6 +23,9 @@ import java.awt.Color; import java.awt.GradientPaint; import org.apache.qpid.disttest.charting.definition.ChartingDefinition; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.title.ShortTextTitle; @@ -30,12 +33,67 @@ import org.jfree.data.general.Dataset; public abstract class BaseChartBuilder implements ChartBuilder { - private static final GradientPaint BLUE_GRADIENT = new GradientPaint(0, 0, Color.white, 0, 1000, Color.blue); + static final GradientPaint BLUE_GRADIENT = new GradientPaint(0, 0, Color.white, 0, 1000, Color.blue); - public void addCommonChartAttributes(JFreeChart chart, ChartingDefinition chartingDefinition) + private SeriesPainter _seriesPainter = new SeriesPainter(); + + private final SeriesBuilder _seriesBuilder; + + protected BaseChartBuilder(SeriesBuilder seriesBuilder) + { + _seriesBuilder = seriesBuilder; + } + + @Override + public JFreeChart buildChart(ChartingDefinition chartingDefinition) + { + _seriesBuilder.setDatasetHolder(newDatasetHolder()); + Dataset dataset = _seriesBuilder.build(chartingDefinition.getSeriesDefinitions()); + + JFreeChart chart = createChart(chartingDefinition, dataset); + return chart; + } + + + /** + * return a holder of an empty dataset suitable for use with the chart type + * returned by {@link #createChartImpl(String, String, String, Dataset, PlotOrientation, boolean, boolean, boolean)}. + */ + protected abstract DatasetHolder newDatasetHolder(); + + /** + * Create a chart with the supplied parameters. + * + * For ease of implementation, the signature is intentionally similar + * to {@link ChartFactory}'s factory methods. + */ + protected abstract JFreeChart createChartImpl( + String title, String xAxisTitle, String yAxisTitle, + final Dataset dataset, + PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls); + + /** + * Create a {@link SeriesStrokeAndPaintApplier} that will be used to format a chart + */ + protected abstract SeriesStrokeAndPaintApplier newStrokeAndPaintApplier(); + + + private JFreeChart createChart(ChartingDefinition chartingDefinition, final Dataset dataset) { + String title = chartingDefinition.getChartTitle(); + String xAxisTitle = chartingDefinition.getXAxisTitle(); + String yAxisTitle = chartingDefinition.getYAxisTitle(); + + final JFreeChart chart = createChartImpl( + title, xAxisTitle, yAxisTitle, + dataset, + PLOT_ORIENTATION, SHOW_LEGEND, SHOW_TOOL_TIPS, SHOW_URLS); + addSubtitle(chart, chartingDefinition); - setBackgroundColour(chart); + chart.setBackgroundPaint(BLUE_GRADIENT); + _seriesPainter.applySeriesAppearance(chart, chartingDefinition.getSeriesDefinitions(), newStrokeAndPaintApplier()); + + return chart; } private void addSubtitle(JFreeChart chart, ChartingDefinition chartingDefinition) @@ -46,13 +104,9 @@ public abstract class BaseChartBuilder implements ChartBuilder } } - private void setBackgroundColour(JFreeChart chart) + void setSeriesPainter(SeriesPainter seriesPainter) { - chart.setBackgroundPaint(BLUE_GRADIENT); + _seriesPainter = seriesPainter; } - public abstract JFreeChart createChartImpl(String title, String xAxisTitle, - String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, - boolean showUrls); - } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java index a6c63f4560..0d08fd8ad1 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryDataSetBasedChartBuilder.java @@ -20,40 +20,36 @@ package org.apache.qpid.disttest.charting.chartbuilder; -import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; -import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.plot.PlotOrientation; import org.jfree.data.category.DefaultCategoryDataset; +import org.jfree.data.general.Dataset; public abstract class CategoryDataSetBasedChartBuilder extends BaseChartBuilder { - private final SeriesBuilder _seriesBuilder; - public CategoryDataSetBasedChartBuilder(SeriesBuilder seriesBuilder) { - _seriesBuilder = seriesBuilder; + super(seriesBuilder); } @Override - public JFreeChart buildChart(ChartingDefinition chartingDefinition) + protected DatasetHolder newDatasetHolder() { - String title = chartingDefinition.getChartTitle(); - String xAxisTitle = chartingDefinition.getXAxisTitle(); - String yAxisTitle = chartingDefinition.getYAxisTitle(); - - final DefaultCategoryDataset dataset = new DefaultCategoryDataset(); - - _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback() + return new DatasetHolder() { + final private DefaultCategoryDataset _dataset = new DefaultCategoryDataset(); + @Override - public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row) + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) { - String x = String.valueOf(row[0]); - double y = Double.parseDouble(row[1].toString()); - dataset.addValue( y, seriesDefinition.getSeriesLegend(), x); + String x = row.dimensionAsString(0); + double y = row.dimensionAsDouble(1); + _dataset.addValue(y, seriesDefinition.getSeriesLegend(), x); } @Override @@ -68,17 +64,33 @@ public abstract class CategoryDataSetBasedChartBuilder extends BaseChartBuilder // unused } - }); + @Override + public int getNumberOfDimensions() + { + return 2; + } - _seriesBuilder.build(chartingDefinition.getSeries()); + @Override + public Dataset getPopulatedDataset() + { + return _dataset; + } + }; + } - JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle, - dataset, PLOT_ORIENTATION, SHOW_LEGEND, SHOW_TOOL_TIPS, SHOW_URLS); + @Override + protected SeriesStrokeAndPaintApplier newStrokeAndPaintApplier() + { + return new CategoryStrokeAndPaintApplier(); + } + @Override + protected final JFreeChart createChartImpl(String title, String xAxisTitle, String yAxisTitle, Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) + { + JFreeChart chart = createCategoryChart(title, xAxisTitle, yAxisTitle, dataset, plotOrientation, showLegend, showToolTips, showUrls); chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45); - - addCommonChartAttributes(chart, chartingDefinition); - return chart; } + + protected abstract JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls); } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryStrokeAndPaintApplier.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryStrokeAndPaintApplier.java new file mode 100644 index 0000000000..cbf5cbe515 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/CategoryStrokeAndPaintApplier.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import java.awt.Color; +import java.awt.Stroke; + +import org.jfree.chart.JFreeChart; + +class CategoryStrokeAndPaintApplier implements SeriesStrokeAndPaintApplier +{ + @Override + public void setSeriesStroke(int seriesIndex, Stroke stroke, JFreeChart targetChart) + { + targetChart.getCategoryPlot().getRenderer().setSeriesStroke(seriesIndex, stroke); + } + + @Override + public void setSeriesPaint(int seriesIndex, Color colour, JFreeChart targetChart) + { + targetChart.getCategoryPlot().getRenderer().setSeriesPaint(seriesIndex, colour); + } +} \ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java index f4e11a2c4d..63a0573676 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactory.java @@ -39,8 +39,10 @@ public class ChartBuilderFactory return new BarChart3DBuilder(seriesBuilder); case XYLINE: return new XYLineChartBuilder(seriesBuilder); + case TIMELINE: + return new TimeSeriesLineChartBuilder(seriesBuilder); case STATISTICAL_BAR: - return new StatisticalBarCharBuilder(seriesBuilder); + return new StatisticalBarChartBuilder(seriesBuilder); default: throw new IllegalArgumentException("Unknown chart type " + chartType); } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactory.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactory.java new file mode 100644 index 0000000000..49d777c506 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactory.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import java.awt.Color; + +public class ColorFactory +{ + /** + * Converts a colour name known to the JDK into a {@link Color} instance. Additionally, + * if the work dark_ is prepended to the colour, a darker shade of the same colour is + * produced. + * + * @param colourName + * @return colour instance + */ + public static Color toColour(String colourName) + { + boolean darkVersion = false; + if (colourName.toLowerCase().startsWith("dark_")) + { + colourName = colourName.replaceFirst("(?i)dark_", ""); + darkVersion = true; + } + + Color colour = getColourFromStaticField(colourName); + if (darkVersion) + { + return colour.darker(); + } + else + { + return colour; + } + } + + private static Color getColourFromStaticField(String colourName) + { + try + { + return (Color) Color.class.getField(colourName.toLowerCase()).get(null); + } + catch (Exception e) + { + throw new RuntimeException("Could not find colour for " + colourName, e); + } + } + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java index 27fff12da0..b92a25f5ac 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChart3DBuilder.java @@ -34,7 +34,7 @@ public class LineChart3DBuilder extends CategoryDataSetBasedChartBuilder } @Override - public JFreeChart createChartImpl(String title, String xAxisTitle, + protected JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) { diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java index 40f3a09b6b..3f5b18acda 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/LineChartBuilder.java @@ -35,7 +35,7 @@ public class LineChartBuilder extends CategoryDataSetBasedChartBuilder } @Override - public JFreeChart createChartImpl(String title, String xAxisTitle, + protected JFreeChart createCategoryChart(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) { diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesPainter.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesPainter.java new file mode 100644 index 0000000000..854635dc87 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesPainter.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.disttest.charting.chartbuilder; + +import java.awt.BasicStroke; +import java.util.List; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.jfree.chart.JFreeChart; + +public class SeriesPainter +{ + public void applySeriesAppearance(JFreeChart chart, List seriesDefinitions, SeriesStrokeAndPaintApplier strokeAndPaintApplier) + { + for (int i = 0; i < seriesDefinitions.size(); i++) + { + SeriesDefinition seriesDefinition = seriesDefinitions.get(i); + if (seriesDefinition.getSeriesColourName() != null) + { + strokeAndPaintApplier.setSeriesPaint(i, ColorFactory.toColour(seriesDefinition.getSeriesColourName()), chart); + } + if (seriesDefinition.getStrokeWidth() != null) + { + // Negative width used to signify dashed + boolean dashed = seriesDefinition.getStrokeWidth() < 0; + float width = Math.abs(seriesDefinition.getStrokeWidth()); + BasicStroke stroke = buildStrokeOfWidth(width, dashed); + strokeAndPaintApplier.setSeriesStroke(i, stroke, chart); + } + } + } + + private BasicStroke buildStrokeOfWidth(float width, boolean dashed) + { + final BasicStroke stroke; + if (dashed) + { + stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f, new float[] {5.0f, 3.0f}, 0.0f); + } + else + { + stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); + } + return stroke; + } +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesStrokeAndPaintApplier.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesStrokeAndPaintApplier.java new file mode 100644 index 0000000000..4d6c37a9f4 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/SeriesStrokeAndPaintApplier.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.disttest.charting.chartbuilder; + +import java.awt.Color; +import java.awt.Stroke; + +import org.jfree.chart.JFreeChart; + +/** + * Applies the supplied stroke and color to a series in the target chart. + * Multiple implementations exist to because of the various chart types. + */ +public interface SeriesStrokeAndPaintApplier +{ + void setSeriesStroke(int seriesIndex, Stroke stroke, JFreeChart targetChart); + void setSeriesPaint(int seriesIndex, Color color, JFreeChart targetChart); +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java deleted file mode 100644 index 86c3f62e09..0000000000 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarCharBuilder.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.disttest.charting.chartbuilder; - -import java.awt.Font; - -import org.apache.qpid.disttest.charting.definition.ChartingDefinition; -import org.apache.qpid.disttest.charting.definition.SeriesDefinition; -import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; -import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.CategoryAxis; -import org.jfree.chart.axis.CategoryLabelPositions; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.axis.ValueAxis; -import org.jfree.chart.plot.CategoryPlot; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.renderer.category.CategoryItemRenderer; -import org.jfree.chart.renderer.category.StatisticalBarRenderer; -import org.jfree.data.general.Dataset; -import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; -import org.jfree.data.statistics.StatisticalCategoryDataset; - -public class StatisticalBarCharBuilder extends BaseChartBuilder -{ - private final SeriesBuilder _seriesBuilder; - - public StatisticalBarCharBuilder(SeriesBuilder seriesBuilder) - { - _seriesBuilder = seriesBuilder; - } - - @Override - public JFreeChart buildChart(ChartingDefinition chartingDefinition) - { - String title = chartingDefinition.getChartTitle(); - String xAxisTitle = chartingDefinition.getXAxisTitle(); - String yAxisTitle = chartingDefinition.getYAxisTitle(); - - final DefaultStatisticalCategoryDataset dataset = new DefaultStatisticalCategoryDataset(); - - _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback() - { - @Override - public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row) - { - String x = String.valueOf(row[0]); - double mean = Double.parseDouble(row[1].toString()); - double stdDev = Double.parseDouble(row[2].toString()); - dataset.add(mean, stdDev, seriesDefinition.getSeriesLegend(), x); - } - - @Override - public void beginSeries(SeriesDefinition seriesDefinition) - { - // unused - } - - @Override - public void endSeries(SeriesDefinition seriesDefinition) - { - // unused - } - - }); - - _seriesBuilder.build(chartingDefinition.getSeries()); - - JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle, dataset, PLOT_ORIENTATION, SHOW_LEGEND, - SHOW_TOOL_TIPS, SHOW_URLS); - - chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45); - - addCommonChartAttributes(chart, chartingDefinition); - - return chart; - } - - @Override - public JFreeChart createChartImpl(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, - PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) - { - CategoryAxis xAxis = new CategoryAxis(xAxisTitle); - ValueAxis yAxis = new NumberAxis(yAxisTitle); - CategoryItemRenderer renderer = new StatisticalBarRenderer(); - - CategoryPlot plot = new CategoryPlot((StatisticalCategoryDataset) dataset, xAxis, yAxis, renderer); - - JFreeChart chart = new JFreeChart(title, new Font("Arial", Font.PLAIN, 10), plot, true); - return chart; - } - -} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarChartBuilder.java new file mode 100644 index 0000000000..c5ad2d7dad --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/StatisticalBarChartBuilder.java @@ -0,0 +1,114 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import java.awt.Font; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.CategoryAxis; +import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.axis.ValueAxis; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.renderer.category.CategoryItemRenderer; +import org.jfree.chart.renderer.category.StatisticalBarRenderer; +import org.jfree.data.general.Dataset; +import org.jfree.data.statistics.DefaultStatisticalCategoryDataset; +import org.jfree.data.statistics.StatisticalCategoryDataset; + +public class StatisticalBarChartBuilder extends BaseChartBuilder +{ + public StatisticalBarChartBuilder(SeriesBuilder seriesBuilder) + { + super(seriesBuilder); + } + + @Override + protected DatasetHolder newDatasetHolder() + { + return new DatasetHolder() + { + private final DefaultStatisticalCategoryDataset _dataset = new DefaultStatisticalCategoryDataset(); + + @Override + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) + { + String x = row.dimensionAsString(0); + double mean = row.dimensionAsDouble(1); + double stdDev = row.dimensionAsDouble(2); + _dataset.add(mean, stdDev, seriesDefinition.getSeriesLegend(), x); + } + + @Override + public void beginSeries(SeriesDefinition seriesDefinition) + { + // unused + } + + @Override + public void endSeries(SeriesDefinition seriesDefinition) + { + // unused + } + + @Override + public int getNumberOfDimensions() + { + return 3; + } + + @Override + public Dataset getPopulatedDataset() + { + return _dataset; + } + }; + } + + @Override + protected SeriesStrokeAndPaintApplier newStrokeAndPaintApplier() + { + return new CategoryStrokeAndPaintApplier(); + } + + @Override + public JFreeChart createChartImpl(String title, String xAxisTitle, String yAxisTitle, final Dataset dataset, + PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) + { + CategoryAxis xAxis = new CategoryAxis(xAxisTitle); + ValueAxis yAxis = new NumberAxis(yAxisTitle); + CategoryItemRenderer renderer = new StatisticalBarRenderer(); + + CategoryPlot plot = new CategoryPlot((StatisticalCategoryDataset) dataset, xAxis, yAxis, renderer); + + JFreeChart chart = new JFreeChart(title, new Font("Arial", Font.PLAIN, 10), plot, true); + + chart.getCategoryPlot().getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45); + + return chart; + } + +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesHolder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesHolder.java new file mode 100644 index 0000000000..803a098dfa --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesHolder.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import java.util.Date; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; +import org.jfree.data.general.Dataset; +import org.jfree.data.time.Millisecond; +import org.jfree.data.time.RegularTimePeriod; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; + +class TimeSeriesHolder implements DatasetHolder +{ + private final TimeSeriesCollection _timeSeriesCollection = new TimeSeriesCollection(); + private TimeSeries _timeSeries; + + @Override + public void beginSeries(SeriesDefinition seriesDefinition) + { + _timeSeries = new TimeSeries(seriesDefinition.getSeriesLegend()); + } + + @Override + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) + { + Date x = row.dimensionAsDate(0); + double y = row.dimensionAsDouble(1); + RegularTimePeriod jfreeChartDate = new Millisecond(x); + _timeSeries.add(jfreeChartDate, y); + } + + @Override + public void endSeries(SeriesDefinition seriesDefinition) + { + _timeSeriesCollection.addSeries(_timeSeries); + } + + @Override + public int getNumberOfDimensions() + { + return 2; + } + + @Override + public Dataset getPopulatedDataset() + { + return _timeSeriesCollection; + } +} \ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesLineChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesLineChartBuilder.java new file mode 100644 index 0000000000..7249ae6332 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesLineChartBuilder.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.data.general.Dataset; +import org.jfree.data.xy.XYDataset; + +public class TimeSeriesLineChartBuilder extends XYDataSetBasedChartBuilder +{ + public TimeSeriesLineChartBuilder(SeriesBuilder seriesBuilder) + { + super(seriesBuilder); + } + + @Override + protected DatasetHolder newDatasetHolder() + { + return new TimeSeriesHolder(); + } + + @Override + public JFreeChart createChartImpl(String title, String xAxisTitle, + String yAxisTitle, final Dataset dataset, PlotOrientation plotOrientation, + boolean showLegend, boolean showToolTips, boolean showUrls) + { + JFreeChart chart = ChartFactory.createTimeSeriesChart( + title, + xAxisTitle, + yAxisTitle, + (XYDataset)dataset, + showLegend, + showToolTips, + showUrls); + + return chart; + } +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java index 87d61ca2ee..575712f06c 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/chartbuilder/XYDataSetBasedChartBuilder.java @@ -19,38 +19,34 @@ */ package org.apache.qpid.disttest.charting.chartbuilder; +import java.awt.Color; +import java.awt.Stroke; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; -import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.CategoryLabelPositions; +import org.jfree.data.general.Dataset; import org.jfree.data.xy.DefaultXYDataset; public abstract class XYDataSetBasedChartBuilder extends BaseChartBuilder { - private final SeriesBuilder _seriesBuilder; - public XYDataSetBasedChartBuilder(SeriesBuilder seriesBuilder) { - this._seriesBuilder = seriesBuilder; + super(seriesBuilder); } @Override - public JFreeChart buildChart(ChartingDefinition chartingDefinition) + protected DatasetHolder newDatasetHolder() { - String title = chartingDefinition.getChartTitle(); - String xAxisTitle = chartingDefinition.getXAxisTitle(); - String yAxisTitle = chartingDefinition.getYAxisTitle(); - - final DefaultXYDataset dataset = new DefaultXYDataset(); - _seriesBuilder.setSeriesBuilderCallback(new SeriesBuilderCallback() + return new DatasetHolder() { + private final DefaultXYDataset _dataset = new DefaultXYDataset(); private List _xyPairs = null; @Override @@ -60,20 +56,24 @@ public abstract class XYDataSetBasedChartBuilder extends BaseChartBuilder } @Override - public void addDataPointToSeries(SeriesDefinition seriesDefinition, - Object[] row) + public void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row) { - double x = Double.parseDouble(row[0].toString()); - double y = Double.parseDouble(row[1].toString()); + double x = row.dimensionAsDouble(0); + double y = row.dimensionAsDouble(1); _xyPairs.add(new Double[] {x, y}); } - @Override public void endSeries(SeriesDefinition seriesDefinition) { double[][] seriesData = listToSeriesDataArray(); - dataset.addSeries(seriesDefinition.getSeriesLegend(), seriesData); + _dataset.addSeries(seriesDefinition.getSeriesLegend(), seriesData); + } + + @Override + public int getNumberOfDimensions() + { + return 2; } private double[][] listToSeriesDataArray() @@ -86,18 +86,34 @@ public abstract class XYDataSetBasedChartBuilder extends BaseChartBuilder seriesData[0][i] = xyPair[0]; seriesData[1][i] = xyPair[1]; i++; - } + } return seriesData; } - }); - - _seriesBuilder.build(chartingDefinition.getSeries()); - JFreeChart chart = createChartImpl(title, xAxisTitle, yAxisTitle, - dataset, PLOT_ORIENTATION, SHOW_LEGEND, SHOW_TOOL_TIPS, SHOW_URLS); + @Override + public Dataset getPopulatedDataset() + { + return _dataset; + } + }; + } - addCommonChartAttributes(chart, chartingDefinition); + @Override + protected SeriesStrokeAndPaintApplier newStrokeAndPaintApplier() + { + return new SeriesStrokeAndPaintApplier() + { + @Override + public void setSeriesStroke(int seriesIndex, Stroke stroke, JFreeChart targetChart) + { + targetChart.getXYPlot().getRenderer().setSeriesStroke(seriesIndex, stroke); + } - return chart; + @Override + public void setSeriesPaint(int seriesIndex, Color colour, JFreeChart targetChart) + { + targetChart.getXYPlot().getRenderer().setSeriesPaint(seriesIndex, colour); + } + }; } } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java index 04b3f7ed3b..bfe47e598e 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinition.java @@ -30,6 +30,7 @@ public class ChartingDefinition private final ChartType _chartType; private final String _chartTitle; private final String _chartSubtitle; + private final String _chartDescription; private final String _xaxisTitle; private final String _yaxisTitle; private final List _seriesDefinitions; @@ -39,12 +40,14 @@ public class ChartingDefinition final ChartType chartType, final String chartTitle, final String chartSubtitle, + final String chartDescription, final String xaxisTitle, final String yaxisTitle, List seriesDefinitions) { _chartStemName = chartStemName; _chartType = chartType; _chartTitle = chartTitle; _chartSubtitle = chartSubtitle; + _chartDescription = chartDescription; _xaxisTitle = xaxisTitle; _yaxisTitle = yaxisTitle; _seriesDefinitions = seriesDefinitions; @@ -65,6 +68,10 @@ public class ChartingDefinition return _chartSubtitle; } + public String getChartDescription() + { + return _chartDescription; + } public String getXAxisTitle() { @@ -77,17 +84,14 @@ public class ChartingDefinition return _yaxisTitle; } - - public ChartType getChartType() { return _chartType; } - public List getSeries() + public List getSeriesDefinitions() { return Collections.unmodifiableList(_seriesDefinitions); } - } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java index 4cbc9318a9..1988f561b6 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreator.java @@ -39,6 +39,7 @@ public class ChartingDefinitionCreator public static final String CHART_TYPE_KEY = "chartType"; public static final String CHART_TITLE_KEY = "chartTitle"; public static final String CHART_SUBTITLE_KEY = "chartSubtitle"; + public static final String CHART_DESCRIPTION_KEY = "chartDescription"; public static final String XAXIS_TITLE_KEY = "xAxisTitle"; public static final String YAXIS_TITLE_KEY = "yAxisTitle"; @@ -82,6 +83,7 @@ public class ChartingDefinitionCreator final ChartType chartType = ChartType.valueOf(props.getProperty(CHART_TYPE_KEY)); final String chartTitle = props.getProperty(CHART_TITLE_KEY); final String chartSubtitle = props.getProperty(CHART_SUBTITLE_KEY); + final String chartDescription = props.getProperty(CHART_DESCRIPTION_KEY); final String xAxisTitle = props.getProperty(XAXIS_TITLE_KEY); final String yAxisTitle = props.getProperty(YAXIS_TITLE_KEY); @@ -91,8 +93,8 @@ public class ChartingDefinitionCreator chartType, chartTitle, chartSubtitle, - xAxisTitle, - yAxisTitle, seriesDefinitions); + chartDescription, + xAxisTitle, yAxisTitle, seriesDefinitions); return chartDefinition; } catch (IOException e) diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java index a39e906957..d89ff855e2 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinition.java @@ -19,17 +19,24 @@ */ package org.apache.qpid.disttest.charting.definition; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + public class SeriesDefinition { private final String _seriesStatement; private final String _seriesLegend; private final String _seriesDirectory; + private final String _seriesColourName; + private final Integer _seriesStrokeWidth; - public SeriesDefinition(String seriesStatement, String seriesLegend, String seriesDirectory) + public SeriesDefinition(String seriesStatement, String seriesLegend, String seriesDirectory, String seriesColourName, Integer seriesStrokeWidth) { _seriesStatement = seriesStatement; _seriesLegend = seriesLegend; _seriesDirectory = seriesDirectory; + _seriesColourName = seriesColourName; + _seriesStrokeWidth = seriesStrokeWidth; } public String getSeriesStatement() @@ -47,4 +54,22 @@ public class SeriesDefinition return _seriesDirectory; } + public String getSeriesColourName() + { + return _seriesColourName; + } + + public Integer getStrokeWidth() + { + return _seriesStrokeWidth; + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("seriesLegend", _seriesLegend) + .append("seriesStatement", _seriesStatement) + .append("seriesDirectory", _seriesDirectory).toString(); + } } diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java index fcc11807c8..d47e7488e1 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreator.java @@ -30,6 +30,8 @@ public class SeriesDefinitionCreator public static final String SERIES_STATEMENT_KEY_FORMAT = "series.%d.statement"; public static final String SERIES_LEGEND_KEY_FORMAT = "series.%d.legend"; public static final String SERIES_DIRECTORY_KEY_FORMAT = "series.%d.dir"; + public static final String SERIES_COLOUR_NAME_FORMAT = "series.%d.colourName"; + public static final String SERIES_STROKE_WIDTH_FORMAT = "series.%d.strokeWidth"; public List createFromProperties(Properties properties) { @@ -42,10 +44,13 @@ public class SeriesDefinitionCreator String seriesStatement = properties.getProperty(String.format(SERIES_STATEMENT_KEY_FORMAT, index)); String seriesLegend = properties.getProperty(String.format(SERIES_LEGEND_KEY_FORMAT, index)); String seriesDir = StrSubstitutor.replaceSystemProperties(properties.getProperty(String.format(SERIES_DIRECTORY_KEY_FORMAT, index))); + String seriesColourName = properties.getProperty(String.format(SERIES_COLOUR_NAME_FORMAT, index)); + Integer seriesStrokeWidth = properties.getProperty(String.format(SERIES_STROKE_WIDTH_FORMAT, index)) == null + ? null : Integer.parseInt(properties.getProperty(String.format(SERIES_STROKE_WIDTH_FORMAT, index))); if (seriesStatement != null) { - final SeriesDefinition seriesDefinition = new SeriesDefinition(seriesStatement, seriesLegend, seriesDir); + final SeriesDefinition seriesDefinition = new SeriesDefinition(seriesStatement, seriesLegend, seriesDir, seriesColourName, seriesStrokeWidth); seriesDefinitions.add(seriesDefinition); } else diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/DatasetHolder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/DatasetHolder.java new file mode 100644 index 0000000000..14fd50facc --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/DatasetHolder.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.seriesbuilder; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.jfree.data.general.Dataset; + +/** + * Accepts data in the form of {@link SeriesDefinition}s and {@link SeriesRow}s, + * and returns it as a {@link Dataset} for use by a JFreeChart chart. + */ +public interface DatasetHolder +{ + int getNumberOfDimensions(); + void beginSeries(SeriesDefinition seriesDefinition); + void addDataPointToSeries(SeriesDefinition seriesDefinition, SeriesRow row); + void endSeries(SeriesDefinition seriesDefinition); + + Dataset getPopulatedDataset(); +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java deleted file mode 100644 index a9adce0afc..0000000000 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilder.java +++ /dev/null @@ -1,141 +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.disttest.charting.seriesbuilder; - -import java.io.File; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Iterator; -import java.util.List; - -import org.apache.qpid.disttest.charting.ChartingException; -import org.apache.qpid.disttest.charting.definition.SeriesDefinition; - -public class JdbcCsvSeriesBuilder implements SeriesBuilder -{ - - static - { - registerCsvDriver(); - } - - private SeriesBuilderCallback _callback; - - @Override - public void setSeriesBuilderCallback(SeriesBuilderCallback callback) - { - this._callback = callback; - } - - @Override - public void build(List seriesDefinitions) - { - for (Iterator iterator = seriesDefinitions.iterator(); iterator.hasNext();) - { - SeriesDefinition series = iterator.next(); - buildDataSetForSingleSeries(series); - } - } - - private void buildDataSetForSingleSeries(SeriesDefinition seriesDefinition) - { - Connection conn = null; - Statement stmt = null; - try - { - File seriesDir = getValidatedSeriesDirectory(seriesDefinition); - - conn = DriverManager.getConnection("jdbc:relique:csv:" + seriesDir.getAbsolutePath()); - - final String seriesStatement = seriesDefinition.getSeriesStatement(); - - stmt = conn.createStatement(); - ResultSet results = stmt.executeQuery(seriesStatement); - int columnCount = results.getMetaData().getColumnCount(); - _callback.beginSeries(seriesDefinition); - while (results.next()) - { - Object[] row = new Object[columnCount]; - for (int i = 0; i < row.length; i++) - { - row[i] = results.getObject(i+1); - } - - _callback.addDataPointToSeries(seriesDefinition, row); - } - _callback.endSeries(seriesDefinition); - } - catch (SQLException e) - { - throw new ChartingException("Failed to create chart dataset", e); - } - finally - { - if (stmt != null) - { - try - { - stmt.close(); - } - catch (SQLException e) - { - throw new RuntimeException("Failed to close statement", e); - } - } - if (conn != null) - { - try - { - conn.close(); - } - catch (SQLException e) - { - throw new RuntimeException("Failed to close connection", e); - } - } - } - } - - private File getValidatedSeriesDirectory(SeriesDefinition series) - { - File seriesDir = new File(series.getSeriesDirectory()); - if (!seriesDir.isDirectory()) - { - throw new ChartingException("seriesDirectory must be a directory : " + seriesDir); - } - return seriesDir; - } - - private static void registerCsvDriver() throws ExceptionInInitializerError - { - try - { - Class.forName("org.relique.jdbc.csv.CsvDriver"); - } - catch (ClassNotFoundException e) - { - throw new RuntimeException("Could not load CSV/JDBC driver", e); - } - } - -} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilder.java new file mode 100644 index 0000000000..180aa54c6d --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilder.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.seriesbuilder; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.disttest.charting.ChartingException; +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.jfree.data.general.Dataset; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A {@link SeriesBuilder} that uses JDBC to read series data. + * The actual JDBC URL used is determined by my {@link JdbcUrlGenerator}. + */ +public class JdbcSeriesBuilder implements SeriesBuilder +{ + private static final Logger LOGGER = LoggerFactory.getLogger(JdbcSeriesBuilder.class); + + private DatasetHolder _datasetHolder; + + private final JdbcUrlGenerator _jdbcUrlGenerator; + + /** + * @param providedJdbcUrl the JDBC URL. Provide null if the value should be + * inferred by {@link #_jdbcUrlGenerator}. + */ + public JdbcSeriesBuilder(String jdbcDriverClass, String providedJdbcUrl) + { + registerDriver(jdbcDriverClass); + _jdbcUrlGenerator = new JdbcUrlGenerator(providedJdbcUrl); + LOGGER.info("Created: " + this); + } + + @Override + public void setDatasetHolder(DatasetHolder callback) + { + _datasetHolder = callback; + } + + @Override + public Dataset build(List seriesDefinitions) + { + for (Iterator iterator = seriesDefinitions.iterator(); iterator.hasNext();) + { + SeriesDefinition series = iterator.next(); + buildDataSetForSingleSeries(series); + } + return _datasetHolder.getPopulatedDataset(); + } + + private void buildDataSetForSingleSeries(SeriesDefinition seriesDefinition) + { + Connection conn = null; + Statement stmt = null; + try + { + String jdbcUrl = _jdbcUrlGenerator.getJdbcUrl(seriesDefinition); + conn = DriverManager.getConnection(jdbcUrl); + + final String seriesStatement = seriesDefinition.getSeriesStatement(); + + stmt = conn.createStatement(); + ResultSet results = stmt.executeQuery(seriesStatement); + int columnCount = results.getMetaData().getColumnCount(); + _datasetHolder.beginSeries(seriesDefinition); + while (results.next()) + { + Object[] row = new Object[columnCount]; + for (int i = 0; i < row.length; i++) + { + row[i] = results.getObject(i+1); + } + + SeriesRow seriesRow = SeriesRow.createValidSeriesRow(_datasetHolder.getNumberOfDimensions(), row); + _datasetHolder.addDataPointToSeries(seriesDefinition, seriesRow); + } + _datasetHolder.endSeries(seriesDefinition); + } + catch (SQLException e) + { + throw new ChartingException("Failed to create chart dataset", e); + } + finally + { + if (stmt != null) + { + try + { + stmt.close(); + } + catch (SQLException e) + { + throw new RuntimeException("Failed to close statement", e); + } + } + if (conn != null) + { + try + { + conn.close(); + } + catch (SQLException e) + { + throw new RuntimeException("Failed to close connection", e); + } + } + } + } + + private void registerDriver(String driverClassName) throws ExceptionInInitializerError + { + try + { + Class.forName(driverClassName); + LOGGER.info("Loaded JDBC driver class " + driverClassName); + } + catch (ClassNotFoundException e) + { + throw new RuntimeException("Could not load JDBC driver " + driverClassName, e); + } + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("jdbcUrlGenerator", _jdbcUrlGenerator) + .toString(); + } +} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGenerator.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGenerator.java new file mode 100644 index 0000000000..77f367b0f1 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGenerator.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.disttest.charting.seriesbuilder; + +import static org.apache.commons.lang.StringUtils.isBlank; +import static org.apache.commons.lang.StringUtils.isNotBlank; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; + +public class JdbcUrlGenerator +{ + private String _providedJdbdUrl; + + public static final String DEFAULT_JDBC_DRIVER_NAME = "org.relique.jdbc.csv.CsvDriver"; + + /** + * Used to create the JDBC URL if one has not been passed in. + */ + private static final String CSV_JDBC_URL_BASE = "jdbc:relique:csv:"; + + /** + * @param providedJdbcUrl the JDBC URL. Provide null if the value should be + * inferred. + */ + public JdbcUrlGenerator(String providedJdbcUrl) + { + _providedJdbdUrl = providedJdbcUrl; + } + + /** + * Returns either the provided value ({@link #_providedJdbdUrl}) + * or a CSV JDBC URL pointing at {@link SeriesDefinition#getSeriesDirectory()} value. + */ + public String getJdbcUrl(SeriesDefinition seriesDefinition) + { + String seriesDir = seriesDefinition.getSeriesDirectory(); + + if(_providedJdbdUrl == null) + { + if(isBlank(seriesDir)) + { + throw new IllegalArgumentException("Neither a series directory nor a JDBC url have been specified. Series definition: " + seriesDefinition); + } + return CSV_JDBC_URL_BASE + seriesDir; + } + else + { + if(isNotBlank(seriesDir)) + { + throw new IllegalArgumentException("Both a series directory '" + seriesDir + "' and a JDBC url have been specified. Series definition: " + seriesDefinition); + } + return _providedJdbdUrl; + } + } + + @Override + public String toString() + { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("providedJdbdUrl", _providedJdbdUrl) + .toString(); + } +} \ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java index 86e471efaf..a865c838c6 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilder.java @@ -22,11 +22,20 @@ package org.apache.qpid.disttest.charting.seriesbuilder; import java.util.List; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.jfree.data.general.Dataset; public interface SeriesBuilder { - void build(List seriesDefinitions); - - void setSeriesBuilderCallback(SeriesBuilderCallback seriesBuilderCallback); + /** + * Uses the supplied {@link SeriesDefinition}s to read the series data + * and pass it to the dataset holder set up in {@link #setDatasetHolder(DatasetHolder)}. + * + * @return the populated dataset + */ + Dataset build(List seriesDefinitions); + /** + * Stores the supplied dataset holder so it can be populated in {@link #build(List)}. + */ + void setDatasetHolder(DatasetHolder datasetHolder); } \ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java deleted file mode 100644 index 7e23953fdb..0000000000 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesBuilderCallback.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.disttest.charting.seriesbuilder; - -import org.apache.qpid.disttest.charting.definition.SeriesDefinition; - -public interface SeriesBuilderCallback -{ - public void beginSeries(SeriesDefinition seriesDefinition); - public void addDataPointToSeries(SeriesDefinition seriesDefinition, Object[] row); - public void endSeries(SeriesDefinition seriesDefinition); - -} diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.java new file mode 100644 index 0000000000..9c16866939 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRow.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.charting.seriesbuilder; + +import java.util.Arrays; +import java.util.Date; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * A data point in a chart. Thinly wraps an array to provide a convenient place to validate the number of dimensions, + * and to access dimensions in a typesafe manner. + */ +public class SeriesRow +{ + private final Object[] _dimensions; + + public static SeriesRow createValidSeriesRow(int expectedNumberOfDimensions, Object[] dimensions) + { + int actualNumberOfDimensions = dimensions.length; + if(expectedNumberOfDimensions != actualNumberOfDimensions) + { + throw new IllegalArgumentException("Expected " + expectedNumberOfDimensions + + " dimensions but found " + actualNumberOfDimensions + + " in: " + Arrays.asList(dimensions)); + } + return new SeriesRow(dimensions); + } + + public SeriesRow(Object... dimensions) + { + _dimensions = dimensions; + } + + public Object dimension(int dimension) + { + return _dimensions[dimension]; + } + + public String dimensionAsString(int dimension) + { + return String.valueOf(dimension(dimension)); + } + + public double dimensionAsDouble(int dimension) + { + return Double.parseDouble(dimensionAsString(dimension)); + } + + public Date dimensionAsDate(int dimension) + { + return (Date) dimension(dimension); + } + + @Override + public int hashCode() + { + return new HashCodeBuilder().append(_dimensions).toHashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (obj == null) + { + return false; + } + if (obj == this) + { + return true; + } + if (obj.getClass() != getClass()) + { + return false; + } + SeriesRow rhs = (SeriesRow) obj; + return new EqualsBuilder().append(_dimensions, rhs._dimensions).isEquals(); + } + + +} \ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java index 5d4a9b6b7e..341f01ccd1 100644 --- a/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java +++ b/java/perftests/visualisation-jfc/src/main/java/org/apache/qpid/disttest/charting/writer/ChartWriter.java @@ -26,10 +26,11 @@ import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.SortedMap; +import java.util.TreeMap; import org.apache.qpid.disttest.charting.ChartingException; +import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; import org.slf4j.Logger; @@ -42,19 +43,19 @@ public class ChartWriter static final String SUMMARY_FILE_NAME = "chart-summary.html"; private File _chartDirectory = new File("."); - private SortedSet _chartFiles = new TreeSet(); + private SortedMap _chartFilesToChartDef = new TreeMap(); - public void writeChartToFileSystem(JFreeChart chart, String chartStemName) + public void writeChartToFileSystem(JFreeChart chart, ChartingDefinition chartDef) { OutputStream pngOutputStream = null; try { - File pngFile = new File(_chartDirectory, chartStemName + ".png"); + File pngFile = new File(_chartDirectory, chartDef.getChartStemName() + ".png"); pngOutputStream = new BufferedOutputStream(new FileOutputStream(pngFile)); ChartUtilities.writeChartAsPNG(pngOutputStream, chart, 600, 400, true, 0); pngOutputStream.close(); - _chartFiles.add(pngFile); + _chartFilesToChartDef.put(pngFile, chartDef); LOGGER.info("Written {} chart", pngFile); } @@ -78,20 +79,21 @@ public class ChartWriter } } - public void writeHtmlSummaryToFileSystem() + public void writeHtmlSummaryToFileSystem(String summaryPageTitle) { - if(_chartFiles.size() < 2) + if(_chartFilesToChartDef.size() < 2) { - LOGGER.info("Only " + _chartFiles.size() + " chart image(s) have been written so no HTML summary file will be produced"); + LOGGER.info("Only {} chart image(s) have been written so no HTML summary file will be produced", _chartFilesToChartDef.size()); return; } - String htmlHeader = + String htmlHeader = String.format( "\n" + " \n" + - " Performance Charts\n" + + " %s\n" + + " \n" + " \n" + - " \n"; + " \n", summaryPageTitle); String htmlFooter = " \n" + @@ -101,22 +103,29 @@ public class ChartWriter try { File summaryFile = new File(_chartDirectory, SUMMARY_FILE_NAME); - LOGGER.debug("About to produce HTML summary file " + summaryFile.getAbsolutePath() + " from charts " + _chartFiles); + LOGGER.debug("About to produce HTML summary file " + summaryFile.getAbsolutePath() + " from charts " + _chartFilesToChartDef); writer = new BufferedWriter(new FileWriter(summaryFile)); writer.write(htmlHeader); writer.write("
    \n"); - for (File chartFile : _chartFiles) + for (File chartFile : _chartFilesToChartDef.keySet()) { writer.write("
  • " + chartFile.getName() + "
  • \n"); } writer.write("
\n"); - for (File chartFile : _chartFiles) + for (File chartFile : _chartFilesToChartDef.keySet()) { - writer.write(" \n"); - writer.write(" \n"); + ChartingDefinition def = _chartFilesToChartDef.get(chartFile); + writer.write("
\n"); + writer.write(" \n"); + writer.write(" \n"); + if (def.getChartDescription() != null) + { + writer.write("
" + def.getChartDescription() + "
\n"); + } + writer.write("
\n"); } writer.write(htmlFooter); writer.close(); @@ -144,5 +153,6 @@ public class ChartWriter public void setOutputDirectory(final File chartDirectory) { _chartDirectory = chartDirectory; + LOGGER.info("Set chart directory: {}", chartDirectory); } } diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilderTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilderTest.java new file mode 100644 index 0000000000..c8a98aafa0 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/BaseChartBuilderTest.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; + +import org.apache.qpid.disttest.charting.definition.ChartingDefinition; +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.test.utils.QpidTestCase; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.CategoryPlot; +import org.jfree.chart.plot.Plot; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.title.TextTitle; +import org.jfree.data.general.Dataset; + +public class BaseChartBuilderTest extends QpidTestCase +{ + private static final String CHART_TITLE = "CHART_TITLE"; + private static final String CHART_SUB_TITLE = "CHART_SUB_TITLE"; + private static final String X_TITLE = "X_TITLE"; + private static final String Y_TITLE = "Y_TITLE"; + + @SuppressWarnings("unchecked") + private List _seriesDefinitions = mock(List.class); + + private ChartingDefinition _chartingDefinition = mock(ChartingDefinition.class); + private SeriesStrokeAndPaintApplier _strokeAndPaintApplier = mock(SeriesStrokeAndPaintApplier.class); + private DatasetHolder _datasetHolder = mock(DatasetHolder.class); + private SeriesPainter _seriesPainter = mock(SeriesPainter.class); + + private SeriesBuilder _seriesBuilder = mock(SeriesBuilder.class); + + private JFreeChart _jFreeChart; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + Plot plot = new CategoryPlot(); + _jFreeChart = new JFreeChart(plot); + + when(_chartingDefinition.getChartTitle()).thenReturn(CHART_TITLE); + when(_chartingDefinition.getChartSubtitle()).thenReturn(CHART_SUB_TITLE); + when(_chartingDefinition.getXAxisTitle()).thenReturn(X_TITLE); + when(_chartingDefinition.getYAxisTitle()).thenReturn(Y_TITLE); + when(_chartingDefinition.getSeriesDefinitions()).thenReturn(_seriesDefinitions ); + } + + public void testBuildChart() + { + BaseChartBuilder chartBuilder = new ChartBuilder(_seriesBuilder, _strokeAndPaintApplier, _datasetHolder) + { + @Override + protected JFreeChart createChartImpl(String title, String xAxisTitle, String yAxisTitle, Dataset dataset, PlotOrientation plotOrientation, boolean showLegend, boolean showToolTips, boolean showUrls) + { + assertEquals(CHART_TITLE, title); + assertEquals(X_TITLE, xAxisTitle); + assertEquals(Y_TITLE, yAxisTitle); + + return _jFreeChart; + } + }; + + JFreeChart chart = chartBuilder.buildChart(_chartingDefinition); + + assertEquals(BaseChartBuilder.BLUE_GRADIENT, chart.getBackgroundPaint()); + assertEquals("The *second* subtitle of the generated chart should have the text from the chart definition", + CHART_SUB_TITLE, ((TextTitle)chart.getSubtitle(1)).getText()); + verify(_seriesPainter).applySeriesAppearance(_jFreeChart, _seriesDefinitions, _strokeAndPaintApplier); + } + + /** + * Extends BaseChartBuilder to allow us to plug in in mock dependencies + */ + private abstract class ChartBuilder extends BaseChartBuilder + { + private SeriesStrokeAndPaintApplier _seriesStrokeAndPaintApplier; + private DatasetHolder _datasetHolder; + + private ChartBuilder(SeriesBuilder seriesBuilder, SeriesStrokeAndPaintApplier seriesStrokeAndPaintApplier, DatasetHolder datasetHolder) + { + super(seriesBuilder); + _seriesStrokeAndPaintApplier = seriesStrokeAndPaintApplier; + _datasetHolder = datasetHolder; + setSeriesPainter(_seriesPainter); + } + + @Override + protected SeriesStrokeAndPaintApplier newStrokeAndPaintApplier() + { + return _seriesStrokeAndPaintApplier; + } + + @Override + protected DatasetHolder newDatasetHolder() + { + return _datasetHolder; + } + } +} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java index e735fb58c6..14f81566a6 100644 --- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartBuilderFactoryTest.java @@ -19,14 +19,13 @@ */ package org.apache.qpid.disttest.charting.chartbuilder; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; import org.apache.qpid.disttest.charting.ChartType; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.test.utils.QpidTestCase; -import junit.framework.TestCase; - -public class ChartBuilderFactoryTest extends TestCase +public class ChartBuilderFactoryTest extends QpidTestCase { private SeriesBuilder _seriesBuilder = mock(SeriesBuilder.class); @@ -59,4 +58,10 @@ public class ChartBuilderFactoryTest extends TestCase ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.XYLINE, _seriesBuilder); assertTrue(builder instanceof XYLineChartBuilder); } + + public void testTimeSeriesLineChart() + { + ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.TIMELINE, _seriesBuilder); + assertTrue(builder instanceof TimeSeriesLineChartBuilder); + } } diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java index 2744e17404..7af3a6b35e 100644 --- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ChartProductionTest.java @@ -19,33 +19,35 @@ */ package org.apache.qpid.disttest.charting.chartbuilder; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.io.File; import java.util.Collections; +import java.util.Date; import java.util.Iterator; import java.util.List; import org.apache.qpid.disttest.charting.ChartType; import org.apache.qpid.disttest.charting.definition.ChartingDefinition; import org.apache.qpid.disttest.charting.definition.SeriesDefinition; -import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilderCallback; +import org.apache.qpid.disttest.charting.seriesbuilder.DatasetHolder; import org.apache.qpid.disttest.charting.seriesbuilder.SeriesBuilder; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; import org.apache.qpid.disttest.charting.writer.ChartWriter; +import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.test.utils.TestFileUtils; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.title.ShortTextTitle; - -import junit.framework.TestCase; +import org.jfree.data.general.Dataset; /** * Tests the production of the different chart types. To manually * verify the generated output, set the system property {@link #RETAIN_TEST_CHARTS} * to prevent the automatic deletion of the test chart directory. - * */ -public class ChartProductionTest extends TestCase +public class ChartProductionTest extends QpidTestCase { private static final String TEST_CHARTTITLE = "TEST_CHARTTITLE"; private static final String TEST_CHARTSUBTITLE = "TEST_CHARTSUBTITLE"; @@ -54,6 +56,16 @@ public class ChartProductionTest extends TestCase private static final String TEST_SERIESLEGEND = "TEST_SERIESLEGEND"; + private static final SeriesRow[] SIMPLE_SERIES_ROWS = new SeriesRow[] + { + new SeriesRow(1d, 1d), + new SeriesRow(2d, 2d), + new SeriesRow(3d, 3d), + new SeriesRow(4d, 4d), + new SeriesRow(5d, 5d), + new SeriesRow(6d, 6d), + }; + private static final String RETAIN_TEST_CHARTS = "retainTestCharts"; private SeriesDefinition _seriesDefinition = mock(SeriesDefinition.class); @@ -66,12 +78,15 @@ public class ChartProductionTest extends TestCase super.setUp(); when(_seriesDefinition.getSeriesLegend()).thenReturn(TEST_SERIESLEGEND); + when(_seriesDefinition.getStrokeWidth()).thenReturn(null); + when(_seriesDefinition.getSeriesColourName()).thenReturn(null); + when(_chartingDefinition.getChartStemName()).thenReturn(getName()); when(_chartingDefinition.getChartTitle()).thenReturn(TEST_CHARTTITLE); when(_chartingDefinition.getChartSubtitle()).thenReturn(TEST_CHARTSUBTITLE); when(_chartingDefinition.getXAxisTitle()).thenReturn(TEST_XAXIS); when(_chartingDefinition.getYAxisTitle()).thenReturn(TEST_YAXIS); - when(_chartingDefinition.getSeries()).thenReturn(Collections.singletonList(_seriesDefinition)); + when(_chartingDefinition.getSeriesDefinitions()).thenReturn(Collections.singletonList(_seriesDefinition)); File chartDir = TestFileUtils.createTestDirectory("charts", false); if (!System.getProperties().containsKey(RETAIN_TEST_CHARTS)) @@ -88,7 +103,7 @@ public class ChartProductionTest extends TestCase public void testBarChart() throws Exception { - ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.BAR, new SampleSeriesBuilder()); + ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.BAR, new SampleSeriesBuilder(SIMPLE_SERIES_ROWS)); assertChartTitlesAndWriteToFile(builder); } @@ -116,36 +131,47 @@ public class ChartProductionTest extends TestCase assertChartTitlesAndWriteToFile(builder); } - public void testStatiscticalBarChart() throws Exception + public void testXYLineChartWithColourAndWidth() throws Exception + { + when(_seriesDefinition.getStrokeWidth()).thenReturn(3); + when(_seriesDefinition.getSeriesColourName()).thenReturn("dark_orange"); + + ChartBuilder builder = ChartBuilderFactory.createChartBuilder(ChartType.XYLINE, new SampleSeriesBuilder()); + assertChartTitlesAndWriteToFile(builder); + } + + public void testTimeSeriesLineChart() throws Exception { + SeriesRow[] timelineSeriesRows = new SeriesRow[] + { + new SeriesRow(new Date(1), 1d), + new SeriesRow(new Date(2), 2d), + new SeriesRow(new Date(3), 3d), + new SeriesRow(new Date(4), 4d), + new SeriesRow(new Date(5), 5d), + new SeriesRow(new Date(6), 6d), + }; + ChartBuilder builder = ChartBuilderFactory.createChartBuilder( + ChartType.TIMELINE, + new SampleSeriesBuilder(timelineSeriesRows)); + + assertChartTitlesAndWriteToFile(builder); + } + + public void testStatisticalBarChart() throws Exception + { + SeriesRow[] statisticalSeriesRows = new SeriesRow[] + { + new SeriesRow(1d, 1d, 0.5d), + new SeriesRow(2d, 2d, 0.4d), + new SeriesRow(4d, 4d, 0.3d), + new SeriesRow(5d, 5d, 0.2d), + new SeriesRow(6d, 6d, 0.1d) + }; + ChartBuilder builder = ChartBuilderFactory.createChartBuilder( ChartType.STATISTICAL_BAR, - new SeriesBuilder() - { - private SeriesBuilderCallback _dataPointCallback; - - @Override - public void build(List seriesDefinitions) - { - for (Iterator iterator = seriesDefinitions.iterator(); iterator.hasNext();) - { - SeriesDefinition seriesDefinition = iterator.next(); - _dataPointCallback.beginSeries(seriesDefinition); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{1d, 1d, 0.5d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{2d, 2d, 0.4d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{4d, 4d, 0.3d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{5d, 5d, 0.2d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{6d, 3d, 0.1d}); - _dataPointCallback.endSeries(seriesDefinition); - } - } - - @Override - public void setSeriesBuilderCallback(SeriesBuilderCallback dataPointCallback) - { - _dataPointCallback = dataPointCallback; - } - }); + new SampleSeriesBuilder(statisticalSeriesRows)); assertChartTitlesAndWriteToFile(builder); } @@ -166,33 +192,43 @@ public class ChartProductionTest extends TestCase assertEquals(1, chart.getCategoryPlot().getDatasetCount()); } - _writer.writeChartToFileSystem(chart, getName()); + _writer.writeChartToFileSystem(chart, _chartingDefinition); } private class SampleSeriesBuilder implements SeriesBuilder { - private SeriesBuilderCallback _dataPointCallback; + private DatasetHolder _datasetHolder; + private SeriesRow[] _sampleSeriesRows = SIMPLE_SERIES_ROWS; + + public SampleSeriesBuilder() + { + } + + public SampleSeriesBuilder(SeriesRow[] sampleSeriesRows) + { + _sampleSeriesRows = sampleSeriesRows; + } @Override - public void build(List seriesDefinitions) + public Dataset build(List seriesDefinitions) { for (Iterator iterator = seriesDefinitions.iterator(); iterator.hasNext();) { SeriesDefinition seriesDefinition = iterator.next(); - _dataPointCallback.beginSeries(seriesDefinition); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{1d, 1d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{2d, 2d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{4d, 4d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{5d, 5d}); - _dataPointCallback.addDataPointToSeries(seriesDefinition, new Object[]{6d, 3d}); - _dataPointCallback.endSeries(seriesDefinition); + _datasetHolder.beginSeries(seriesDefinition); + for(SeriesRow seriesRow : _sampleSeriesRows) + { + _datasetHolder.addDataPointToSeries(seriesDefinition, seriesRow); + } + _datasetHolder.endSeries(seriesDefinition); } + return _datasetHolder.getPopulatedDataset(); } @Override - public void setSeriesBuilderCallback(SeriesBuilderCallback dataPointCallback) + public void setDatasetHolder(DatasetHolder dataPointCallback) { - _dataPointCallback = dataPointCallback; + _datasetHolder = dataPointCallback; } } } diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactoryTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactoryTest.java new file mode 100644 index 0000000000..2656c780bb --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/ColorFactoryTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.chartbuilder; + +import java.awt.Color; + +import org.apache.qpid.test.utils.QpidTestCase; + +public class ColorFactoryTest extends QpidTestCase +{ + public void testBlue() + { + assertEquals(Color.blue, ColorFactory.toColour("blue")); + assertEquals(Color.blue, ColorFactory.toColour("BLUE")); + assertEquals(Color.blue, ColorFactory.toColour("Blue")); + } + + public void testDarkBlue() + { + assertEquals(Color.blue.darker(), ColorFactory.toColour("dark_blue")); + assertEquals(Color.blue.darker(), ColorFactory.toColour("DARK_BLUE")); + assertEquals(Color.blue.darker(), ColorFactory.toColour("Dark_Blue")); + } + +} \ No newline at end of file diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesBuilderCallbackTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesBuilderCallbackTest.java new file mode 100644 index 0000000000..cb89511389 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/chartbuilder/TimeSeriesBuilderCallbackTest.java @@ -0,0 +1,72 @@ +package org.apache.qpid.disttest.charting.chartbuilder; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.apache.qpid.disttest.charting.seriesbuilder.SeriesRow; +import org.apache.qpid.test.utils.QpidTestCase; +import org.jfree.data.time.TimeSeries; +import org.jfree.data.time.TimeSeriesCollection; +import org.jfree.data.time.TimeSeriesDataItem; + +public class TimeSeriesBuilderCallbackTest extends QpidTestCase +{ + private static final String SERIES_LEGEND = "mySeriesLegend"; + + private static final int NUMBER_OF_DATA_POINTS = 3; + + private Date[] _dates; + private double[] _values; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+00:00")); + + calendar.set(2013, Calendar.JANUARY, 1); + Date jan1 = calendar.getTime(); + + calendar.set(2013, Calendar.JANUARY, 2); + Date jan2 = calendar.getTime(); + + calendar.set(2013, Calendar.JANUARY, 3); + Date jan3 = calendar.getTime(); + + _dates = new Date[] {jan1, jan2, jan3}; + _values = new double[] {2.0, 4.0, 8.0}; + } + + + public void testAddPointToSeries() + { + TimeSeriesHolder timeSeriesHolder = new TimeSeriesHolder(); + + SeriesDefinition seriesDefinition = mock(SeriesDefinition.class); + when(seriesDefinition.getSeriesLegend()).thenReturn(SERIES_LEGEND); + + timeSeriesHolder.beginSeries(seriesDefinition); + + timeSeriesHolder.addDataPointToSeries(seriesDefinition, new SeriesRow(_dates[0], _values[0])); + timeSeriesHolder.addDataPointToSeries(seriesDefinition, new SeriesRow(_dates[1], _values[1])); + timeSeriesHolder.addDataPointToSeries(seriesDefinition, new SeriesRow(_dates[2], _values[2])); + + timeSeriesHolder.endSeries(seriesDefinition); + + TimeSeriesCollection timeSeriesCollection = (TimeSeriesCollection) timeSeriesHolder.getPopulatedDataset(); + + TimeSeries actualTimeSeries = timeSeriesCollection.getSeries(SERIES_LEGEND); + for(int i = 0; i < NUMBER_OF_DATA_POINTS; i++) + { + TimeSeriesDataItem dataItem0 = actualTimeSeries.getDataItem(i); + assertEquals(_dates[i].getTime(), dataItem0.getPeriod().getMiddleMillisecond()); + assertEquals(_values[i], dataItem0.getValue()); + } + } + +} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java index 5371f3df45..e4b4d4d272 100644 --- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/ChartingDefinitionCreatorTest.java @@ -19,8 +19,9 @@ */ package org.apache.qpid.disttest.charting.definition; -import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_TITLE_KEY; +import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_DESCRIPTION_KEY; import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_SUBTITLE_KEY; +import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_TITLE_KEY; import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.CHART_TYPE_KEY; import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.XAXIS_TITLE_KEY; import static org.apache.qpid.disttest.charting.definition.ChartingDefinitionCreator.YAXIS_TITLE_KEY; @@ -31,15 +32,15 @@ import java.io.FileWriter; import java.util.List; import java.util.Properties; -import junit.framework.TestCase; - import org.apache.qpid.disttest.charting.ChartType; import org.apache.qpid.disttest.charting.ChartingException; +import org.apache.qpid.test.utils.QpidTestCase; -public class ChartingDefinitionCreatorTest extends TestCase +public class ChartingDefinitionCreatorTest extends QpidTestCase { private static final String TEST_CHART_TITLE = "CHART_TITLE"; private static final String TEST_CHART_SUBTITLE = "CHART_SUBTITLE"; + private static final String TEST_CHART_DESCRIPTION = "CHART_DESCRIPTION"; private static final String TEST_XAXIS_TITLE = "XAXIS_TITLE"; private static final String TEST_YAXIS_TITLE = "YAXIS_TITLE"; private static final ChartType TEST_CHART_TYPE = ChartType.LINE; @@ -86,6 +87,7 @@ public class ChartingDefinitionCreatorTest extends TestCase ChartingDefinition definition1 = definitions.get(0); assertEquals(TEST_CHART_TITLE, definition1.getChartTitle()); assertEquals(TEST_CHART_SUBTITLE, definition1.getChartSubtitle()); + assertEquals(TEST_CHART_DESCRIPTION, definition1.getChartDescription()); assertEquals(TEST_XAXIS_TITLE, definition1.getXAxisTitle()); assertEquals(TEST_YAXIS_TITLE, definition1.getYAxisTitle()); assertEquals(TEST_CHART_TYPE, definition1.getChartType()); @@ -93,7 +95,7 @@ public class ChartingDefinitionCreatorTest extends TestCase String stemOnly = testDefFile.getName().replaceFirst("\\.chartdef", ""); assertEquals(stemOnly, definition1.getChartStemName()); - final List seriesDefinitions = definition1.getSeries(); + final List seriesDefinitions = definition1.getSeriesDefinitions(); assertEquals(1, seriesDefinitions.size()); SeriesDefinition seriesDefinition = seriesDefinitions.get(0); assertEquals(TEST_SERIES_SELECT_STATEMENT, seriesDefinition.getSeriesStatement()); @@ -125,6 +127,7 @@ public class ChartingDefinitionCreatorTest extends TestCase props.setProperty(CHART_TYPE_KEY, TEST_CHART_TYPE.name()); props.setProperty(CHART_TITLE_KEY, TEST_CHART_TITLE); props.setProperty(CHART_SUBTITLE_KEY, TEST_CHART_SUBTITLE); + props.setProperty(CHART_DESCRIPTION_KEY, TEST_CHART_DESCRIPTION); props.setProperty(XAXIS_TITLE_KEY, TEST_XAXIS_TITLE); props.setProperty(YAXIS_TITLE_KEY, TEST_YAXIS_TITLE); diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreatorTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreatorTest.java index 2187793c53..ef605024cc 100644 --- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreatorTest.java +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/definition/SeriesDefinitionCreatorTest.java @@ -19,20 +19,24 @@ */ package org.apache.qpid.disttest.charting.definition; +import static org.apache.qpid.disttest.charting.definition.SeriesDefinitionCreator.SERIES_COLOUR_NAME_FORMAT; import static org.apache.qpid.disttest.charting.definition.SeriesDefinitionCreator.SERIES_DIRECTORY_KEY_FORMAT; import static org.apache.qpid.disttest.charting.definition.SeriesDefinitionCreator.SERIES_LEGEND_KEY_FORMAT; import static org.apache.qpid.disttest.charting.definition.SeriesDefinitionCreator.SERIES_STATEMENT_KEY_FORMAT; +import static org.apache.qpid.disttest.charting.definition.SeriesDefinitionCreator.SERIES_STROKE_WIDTH_FORMAT; import java.util.List; import java.util.Properties; -import junit.framework.TestCase; +import org.apache.qpid.test.utils.QpidTestCase; -public class SeriesDefinitionCreatorTest extends TestCase +public class SeriesDefinitionCreatorTest extends QpidTestCase { private static final String TEST_SERIES_1_SELECT_STATEMENT = "SERIES_1_SELECT_STATEMENT"; private static final String TEST_SERIES_1_LEGEND = "SERIES_1_LEGEND"; private static final String TEST_SERIES_1_DIR = "SERIES_1_DIR"; + private static final String TEST_SERIES_1_COLOUR_NAME = "seriesColourName"; + private static final Integer TEST_SERIES_1_STROKE_WIDTH = 1;; private static final String TEST_SERIES_1_DIR_WITH_SYSPROP = "${java.io.tmpdir}/mydir"; @@ -52,7 +56,7 @@ public class SeriesDefinitionCreatorTest extends TestCase public void testOneSeriesDefinition() throws Exception { - createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR); + createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR, TEST_SERIES_1_COLOUR_NAME, TEST_SERIES_1_STROKE_WIDTH); List definitions = _seriesDefinitionLoader.createFromProperties(_properties); assertEquals(1, definitions.size()); @@ -61,12 +65,14 @@ public class SeriesDefinitionCreatorTest extends TestCase assertEquals(TEST_SERIES_1_SELECT_STATEMENT, definition.getSeriesStatement()); assertEquals(TEST_SERIES_1_LEGEND, definition.getSeriesLegend()); assertEquals(TEST_SERIES_1_DIR, definition.getSeriesDirectory()); + assertEquals(TEST_SERIES_1_COLOUR_NAME, definition.getSeriesColourName()); + assertEquals(TEST_SERIES_1_STROKE_WIDTH, definition.getStrokeWidth()); } public void testTwoSeriesDefinitions() throws Exception { - createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR); - createTestProperties(2, TEST_SERIES_2_SELECT_STATEMENT, TEST_SERIES_2_LEGEND, TEST_SERIES_2_DIR); + createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR, TEST_SERIES_1_COLOUR_NAME, TEST_SERIES_1_STROKE_WIDTH); + createTestProperties(2, TEST_SERIES_2_SELECT_STATEMENT, TEST_SERIES_2_LEGEND, TEST_SERIES_2_DIR, null, null); List definitions = _seriesDefinitionLoader.createFromProperties(_properties); assertEquals(2, definitions.size()); @@ -84,8 +90,8 @@ public class SeriesDefinitionCreatorTest extends TestCase public void testNonSequentialSeriesDefinitionsIgnored() throws Exception { - createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR); - createTestProperties(3, TEST_SERIES_2_SELECT_STATEMENT, TEST_SERIES_2_LEGEND, TEST_SERIES_2_DIR); + createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR, TEST_SERIES_1_COLOUR_NAME, TEST_SERIES_1_STROKE_WIDTH); + createTestProperties(3, TEST_SERIES_2_SELECT_STATEMENT, TEST_SERIES_2_LEGEND, TEST_SERIES_2_DIR, null, null); List definitions = _seriesDefinitionLoader.createFromProperties(_properties); assertEquals(1, definitions.size()); @@ -94,7 +100,7 @@ public class SeriesDefinitionCreatorTest extends TestCase public void testSeriesDirectorySubstitution() throws Exception { final String tmpDir = System.getProperty("java.io.tmpdir"); - createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR_WITH_SYSPROP); + createTestProperties(1, TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, TEST_SERIES_1_DIR_WITH_SYSPROP, null, null); List definitions = _seriesDefinitionLoader.createFromProperties(_properties); assertEquals(1, definitions.size()); @@ -103,11 +109,19 @@ public class SeriesDefinitionCreatorTest extends TestCase assertTrue(seriesDefinition1.getSeriesDirectory().startsWith(tmpDir)); } - private void createTestProperties(int index, String selectStatement, String seriesLegend, String seriesDir) throws Exception + private void createTestProperties(int index, String selectStatement, String seriesLegend, String seriesDir, String seriesColourName, Integer seriesStrokeWidth) throws Exception { _properties.setProperty(String.format(SERIES_STATEMENT_KEY_FORMAT, index), selectStatement); _properties.setProperty(String.format(SERIES_LEGEND_KEY_FORMAT, index), seriesLegend); _properties.setProperty(String.format(SERIES_DIRECTORY_KEY_FORMAT, index), seriesDir); + if (seriesColourName != null) + { + _properties.setProperty(String.format(SERIES_COLOUR_NAME_FORMAT, index), seriesColourName); + } + if (seriesStrokeWidth != null) + { + _properties.setProperty(String.format(SERIES_STROKE_WIDTH_FORMAT, index), seriesStrokeWidth.toString()); + } } } diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilderTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilderTest.java deleted file mode 100644 index 5148a25bec..0000000000 --- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcCsvSeriesBuilderTest.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.disttest.charting.seriesbuilder; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.PrintWriter; -import java.util.Collections; - -import junit.framework.TestCase; - -import org.apache.qpid.disttest.charting.definition.SeriesDefinition; -import org.apache.qpid.disttest.charting.seriesbuilder.JdbcCsvSeriesBuilder; - -public class JdbcCsvSeriesBuilderTest extends TestCase -{ - private static final String TEST_SERIES_1_SELECT_STATEMENT = "SELECT A, B FROM test"; - private static final String TEST_SERIES_1_LEGEND = "SERIES_1_LEGEND"; - - private SeriesBuilderCallback _seriesWalkerCallback = mock(SeriesBuilderCallback.class); - private JdbcCsvSeriesBuilder _seriesBuilder = new JdbcCsvSeriesBuilder(); - - private File _testTempDir; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - _seriesBuilder.setSeriesBuilderCallback(_seriesWalkerCallback); - _testTempDir = createTestTemporaryDirectory(); - } - - public void testBuildOneSeries() throws Exception - { - createTestCsvIn(_testTempDir); - SeriesDefinition seriesDefinition = createTestSeriesDefinition(); - - _seriesBuilder.build(Collections.singletonList(seriesDefinition)); - - verify(_seriesWalkerCallback).beginSeries(seriesDefinition); - verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new Object[]{"elephant", "2"}); - verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new Object[]{"lion", "3"}); - verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new Object[]{"tiger", "4"}); - verify(_seriesWalkerCallback).endSeries(seriesDefinition); - } - - private void createTestCsvIn(File testDir) throws Exception - { - File csv = new File(_testTempDir, "test.csv"); - - PrintWriter csvWriter = new PrintWriter(new BufferedWriter(new FileWriter(csv))); - csvWriter.println("A,B"); - csvWriter.println("elephant,2"); - csvWriter.println("lion,3"); - csvWriter.println("tiger,4"); - csvWriter.close(); - } - - private SeriesDefinition createTestSeriesDefinition() - { - SeriesDefinition definition = new SeriesDefinition(TEST_SERIES_1_SELECT_STATEMENT, TEST_SERIES_1_LEGEND, _testTempDir.getAbsolutePath()); - return definition; - } - - private File createTestTemporaryDirectory() throws Exception - { - File tmpDir = new File(System.getProperty("java.io.tmpdir"), "testdef" + System.nanoTime()); - tmpDir.mkdirs(); - tmpDir.deleteOnExit(); - return tmpDir; - } - -} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilderTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilderTest.java new file mode 100644 index 0000000000..b6b4dbe56b --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcSeriesBuilderTest.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.disttest.charting.seriesbuilder; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.util.Collections; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.apache.qpid.test.utils.QpidTestCase; + +public class JdbcSeriesBuilderTest extends QpidTestCase +{ + private static final String TEST_SERIES_1_SELECT_STATEMENT = "SELECT A, B FROM test"; + private static final String TEST_SERIES_1_LEGEND = "SERIES_1_LEGEND"; + private static final String TEST_SERIES1_COLOUR_NAME = "blue"; + private static final Integer TEST_SERIES1_STROKE_WIDTH = 3; + + private DatasetHolder _seriesWalkerCallback = mock(DatasetHolder.class); + + private File _testTempDir; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + when(_seriesWalkerCallback.getNumberOfDimensions()).thenReturn(2); + _testTempDir = createTestTemporaryDirectory(); + createTestCsvIn(_testTempDir); + } + + public void testBuildOneSeries() throws Exception + { + SeriesDefinition seriesDefinition = createTestSeriesDefinition(); + + JdbcSeriesBuilder seriesBuilder = new JdbcSeriesBuilder("org.relique.jdbc.csv.CsvDriver", null); + + seriesBuilder.setDatasetHolder(_seriesWalkerCallback); + + seriesBuilder.build(Collections.singletonList(seriesDefinition)); + + verify(_seriesWalkerCallback).beginSeries(seriesDefinition); + verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new SeriesRow("elephant", "2")); + verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new SeriesRow("lion", "3")); + verify(_seriesWalkerCallback).addDataPointToSeries(seriesDefinition, new SeriesRow("tiger", "4")); + verify(_seriesWalkerCallback).endSeries(seriesDefinition); + } + + private void createTestCsvIn(File testDir) throws Exception + { + File csv = new File(_testTempDir, "test.csv"); + + PrintWriter csvWriter = new PrintWriter(new BufferedWriter(new FileWriter(csv))); + csvWriter.println("A,B"); + csvWriter.println("elephant,2"); + csvWriter.println("lion,3"); + csvWriter.println("tiger,4"); + csvWriter.close(); + } + + private SeriesDefinition createTestSeriesDefinition() + { + SeriesDefinition definition = new SeriesDefinition( + TEST_SERIES_1_SELECT_STATEMENT, + TEST_SERIES_1_LEGEND, + _testTempDir.getAbsolutePath(), + TEST_SERIES1_COLOUR_NAME, + TEST_SERIES1_STROKE_WIDTH); + return definition; + } + + private File createTestTemporaryDirectory() throws Exception + { + File tmpDir = new File(System.getProperty("java.io.tmpdir"), "testdef" + System.nanoTime()); + tmpDir.mkdirs(); + tmpDir.deleteOnExit(); + return tmpDir; + } + +} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGeneratorTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGeneratorTest.java new file mode 100644 index 0000000000..d53d0ccfe1 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/JdbcUrlGeneratorTest.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.charting.seriesbuilder; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.qpid.disttest.charting.definition.SeriesDefinition; +import org.apache.qpid.test.utils.QpidTestCase; + +public class JdbcUrlGeneratorTest extends QpidTestCase +{ + public void testGetJdbcUrlWithoutProvidingAUrlReturnsCsvUrlWithCorrectDirectory() + { + JdbcUrlGenerator jdbcUrlGenerator = new JdbcUrlGenerator(null); + SeriesDefinition seriesDefinition = mock(SeriesDefinition.class); + when(seriesDefinition.getSeriesDirectory()).thenReturn("mydir"); + + String jdbcUrl = jdbcUrlGenerator.getJdbcUrl(seriesDefinition); + + assertEquals("jdbc:relique:csv:mydir", jdbcUrl); + } + + public void testGetJdbcUrlReturnsProvidedUrl() + { + String urlTemplate = "urlTemplate"; + JdbcUrlGenerator jdbcUrlGenerator = new JdbcUrlGenerator(urlTemplate); + SeriesDefinition seriesDefinition = mock(SeriesDefinition.class); + + String jdbcUrl = jdbcUrlGenerator.getJdbcUrl(seriesDefinition); + + assertEquals(urlTemplate, jdbcUrl); + } + + public void testGetJdbcUrlThrowsExceptionIfUrlProvidedAndSeriesDirectorySpecified() + { + String urlTemplate = "urlTemplate"; + JdbcUrlGenerator jdbcUrlGenerator = new JdbcUrlGenerator(urlTemplate); + SeriesDefinition seriesDefinition = mock(SeriesDefinition.class); + when(seriesDefinition.getSeriesDirectory()).thenReturn("mydir"); + + try + { + jdbcUrlGenerator.getJdbcUrl(seriesDefinition); + fail("Expected exception not thrown"); + } + catch (IllegalArgumentException e) + { + // pass + } + } + + public void testGetJdbcUrlThrowsExceptionWithoutAProvidedUrlOrSeriesDirectory() + { + JdbcUrlGenerator jdbcUrlGenerator = new JdbcUrlGenerator(null); + SeriesDefinition seriesDefinition = mock(SeriesDefinition.class); + when(seriesDefinition.getSeriesDirectory()).thenReturn(null); + + try + { + jdbcUrlGenerator.getJdbcUrl(seriesDefinition); + fail("Expected exception not thrown"); + } + catch (IllegalArgumentException e) + { + // pass + } + } +} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRowTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRowTest.java new file mode 100644 index 0000000000..064971aa35 --- /dev/null +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/seriesbuilder/SeriesRowTest.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.disttest.charting.seriesbuilder; + +import org.apache.qpid.test.utils.QpidTestCase; + +public class SeriesRowTest extends QpidTestCase +{ + private static final Integer[] PAIR = new Integer[] {10, 11}; + + public void testValidSeriesRow() + { + assertEquals(11, SeriesRow.createValidSeriesRow(2, PAIR).dimension(1)); + } + + public void testValidSeriesRowThrowsExceptionIfArrayTooSmall() + { + try + { + SeriesRow.createValidSeriesRow(1, PAIR); + fail("Expected exception not thrown"); + } + catch(IllegalArgumentException e) + { + // pass + } + } + + public void testDimension() + { + SeriesRow seriesRow = new SeriesRow(10, 11); + assertEquals(10, seriesRow.dimension(0)); + assertEquals(11, seriesRow.dimension(1)); + } + + public void testDimensionAsString() + { + SeriesRow seriesRow = new SeriesRow(10); + assertEquals("10", seriesRow.dimensionAsString(0)); + } + + public void testDimensionAsDouble() + { + SeriesRow seriesRow = new SeriesRow(10.1); + assertEquals(10.1, seriesRow.dimensionAsDouble(0), 0.0); + } + +} diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/ChartWriterTest.java b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/ChartWriterTest.java index 0e176d326b..9703c66e1f 100644 --- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/ChartWriterTest.java +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/ChartWriterTest.java @@ -20,20 +20,23 @@ */ package org.apache.qpid.disttest.charting.writer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.io.File; import java.io.FileWriter; import java.io.InputStream; import java.util.Scanner; -import junit.framework.TestCase; - +import org.apache.qpid.disttest.charting.definition.ChartingDefinition; +import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.test.utils.TestFileUtils; import org.apache.qpid.util.FileUtils; import org.jfree.chart.ChartFactory; import org.jfree.chart.JFreeChart; import org.jfree.data.general.DefaultPieDataset; -public class ChartWriterTest extends TestCase +public class ChartWriterTest extends QpidTestCase { private JFreeChart _chart1; private JFreeChart _chart2; @@ -59,24 +62,34 @@ public class ChartWriterTest extends TestCase public void testWriteChartToFileSystem() { + ChartingDefinition chartDef1 = mock(ChartingDefinition.class); + when(chartDef1.getChartStemName()).thenReturn("chart1"); + File chart1File = new File(_chartDir, "chart1.png"); assertFalse("chart1 png should not exist yet", chart1File.exists()); - _writer.writeChartToFileSystem(_chart1, "chart1"); + _writer.writeChartToFileSystem(_chart1, chartDef1); assertTrue("chart1 png does not exist", chart1File.exists()); } public void testWriteHtmlSummaryToFileSystemOverwritingExistingFile() throws Exception { + ChartingDefinition chartDef1 = mock(ChartingDefinition.class); + when(chartDef1.getChartStemName()).thenReturn("chart1"); + when(chartDef1.getChartDescription()).thenReturn("chart description1"); + + ChartingDefinition chartDef2 = mock(ChartingDefinition.class); + when(chartDef2.getChartStemName()).thenReturn("chart2"); + File summaryFile = new File(_chartDir, ChartWriter.SUMMARY_FILE_NAME); writeDummyContentToSummaryFileToEnsureItGetsOverwritten(summaryFile); - _writer.writeChartToFileSystem(_chart2, "chart2"); - _writer.writeChartToFileSystem(_chart1, "chart1"); + _writer.writeChartToFileSystem(_chart2, chartDef2); + _writer.writeChartToFileSystem(_chart1, chartDef1); - _writer.writeHtmlSummaryToFileSystem(); + _writer.writeHtmlSummaryToFileSystem("Performance Charts"); InputStream expectedSummaryFileInputStream = getClass().getResourceAsStream("expected-chart-summary.html"); String expectedSummaryContent = new Scanner(expectedSummaryFileInputStream).useDelimiter("\\A").next(); @@ -87,11 +100,15 @@ public class ChartWriterTest extends TestCase public void testWriteHtmlSummaryToFileSystemDoesNothingIfLessThanTwoCharts() { + ChartingDefinition chartDef1 = mock(ChartingDefinition.class); + when(chartDef1.getChartStemName()).thenReturn("chart1"); + when(chartDef1.getChartDescription()).thenReturn("chart description1"); + File summaryFile = new File(_chartDir, ChartWriter.SUMMARY_FILE_NAME); - _writer.writeChartToFileSystem(_chart1, "chart1"); + _writer.writeChartToFileSystem(_chart1, chartDef1); - _writer.writeHtmlSummaryToFileSystem(); + _writer.writeHtmlSummaryToFileSystem("Performance Charts"); assertFalse("Only one chart generated so no summary file should have been written", summaryFile.exists()); diff --git a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/expected-chart-summary.html b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/expected-chart-summary.html index 89c508a77e..e7dadcb05b 100755 --- a/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/expected-chart-summary.html +++ b/java/perftests/visualisation-jfc/src/test/java/org/apache/qpid/disttest/charting/writer/expected-chart-summary.html @@ -1,15 +1,21 @@ Performance Charts + - - - - +
+ + +
chart description1
+
+
+ + +
\ No newline at end of file diff --git a/java/systests/build.xml b/java/systests/build.xml index 57337bdc55..dee73b2e1e 100644 --- a/java/systests/build.xml +++ b/java/systests/build.xml @@ -32,7 +32,9 @@ nn - or more contributor license agreements. See the NOTICE file - + + diff --git a/java/systests/etc/config-systests-bdb-settings.xml b/java/systests/etc/config-systests-bdb-settings.xml deleted file mode 100644 index 4fa69d0abc..0000000000 --- a/java/systests/etc/config-systests-bdb-settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - ${QPID_HOME}/etc/virtualhosts-systests-bdb.xml - - - diff --git a/java/systests/etc/config-systests-bdb.xml b/java/systests/etc/config-systests-bdb.xml deleted file mode 100644 index 6b17b564a8..0000000000 --- a/java/systests/etc/config-systests-bdb.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - diff --git a/java/systests/etc/config-systests-derby-mem-settings.xml b/java/systests/etc/config-systests-derby-mem-settings.xml deleted file mode 100644 index 69369d9ac9..0000000000 --- a/java/systests/etc/config-systests-derby-mem-settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - ${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml - - - diff --git a/java/systests/etc/config-systests-derby-mem.xml b/java/systests/etc/config-systests-derby-mem.xml deleted file mode 100644 index 8e40df986e..0000000000 --- a/java/systests/etc/config-systests-derby-mem.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - diff --git a/java/systests/etc/config-systests-derby-settings.xml b/java/systests/etc/config-systests-derby-settings.xml deleted file mode 100644 index 3ed3a9e33b..0000000000 --- a/java/systests/etc/config-systests-derby-settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - ${QPID_HOME}/etc/virtualhosts-systests-derby.xml - - - diff --git a/java/systests/etc/config-systests-derby.xml b/java/systests/etc/config-systests-derby.xml deleted file mode 100644 index 21a7a8cabe..0000000000 --- a/java/systests/etc/config-systests-derby.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - diff --git a/java/systests/etc/config-systests-firewall-2.xml b/java/systests/etc/config-systests-firewall-2.xml deleted file mode 100644 index 5167d88f12..0000000000 --- a/java/systests/etc/config-systests-firewall-2.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - ${QPID_HOME} - ${QPID_WORK} - ${prefix}/etc - ${QPID_HOME}/lib/plugins - ${QPID_WORK}/cache - - - - false - 8672 - false - /path/to/keystore.ks - keystorepass - - 5672 - 262144 - 262144 - - - false - - - 65535 - en_US - - - - - - org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase - - - passwordFile - ${conf}/passwd - - - - - - false - - - - - ${conf}/virtualhosts-systests-firewall-2.xml - - - 0 - 2.0 - - - true - - - ON - - - - diff --git a/java/systests/etc/config-systests-firewall-3.xml b/java/systests/etc/config-systests-firewall-3.xml deleted file mode 100644 index 2bcbf53a39..0000000000 --- a/java/systests/etc/config-systests-firewall-3.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - ${QPID_HOME} - ${QPID_WORK} - ${prefix}/etc - ${QPID_HOME}/lib/plugins - ${QPID_WORK}/cache - - - - false - 8672 - false - /path/to/keystore.ks - keystorepass - - 5672 - 262144 - 262144 - - - false - - - 65535 - en_US - - - - - - org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase - - - passwordFile - ${conf}/passwd - - - - - - false - - - - - - - ${conf}/virtualhosts-systests-firewall-3.xml - - - 0 - 2.0 - - - true - - - ON - - - - diff --git a/java/systests/etc/config-systests-firewall-settings.xml b/java/systests/etc/config-systests-firewall-settings.xml deleted file mode 100644 index aa73be0646..0000000000 --- a/java/systests/etc/config-systests-firewall-settings.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - ${QPID_HOME}/etc/virtualhosts-systests-firewall.xml - diff --git a/java/systests/etc/config-systests-firewall.xml b/java/systests/etc/config-systests-firewall.xml deleted file mode 100644 index a884a39614..0000000000 --- a/java/systests/etc/config-systests-firewall.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - diff --git a/java/systests/etc/config-systests-settings.xml b/java/systests/etc/config-systests-settings.xml deleted file mode 100644 index 0b65ad83c3..0000000000 --- a/java/systests/etc/config-systests-settings.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - ${QPID_HOME} - ${QPID_WORK} - ${prefix}/etc - - ${QPID_HOME}/lib/plugins - ${QPID_WORK}/cache - - - - - 15671 - false - false - ${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks - password - - 5672 - 262144 - 262144 - - - false - - 8999 - - - - false - ${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks - password - - - false - - - - 65535 - en_US - - - - - - org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase - - - passwordFile - ${conf}/passwd - - - - - - - - - - false - - - ${QPID_HOME}/etc/virtualhosts-systests.xml - - - 0 - 2.0 - - - true - - - ON - - diff --git a/java/systests/etc/config-systests.json b/java/systests/etc/config-systests.json new file mode 100644 index 0000000000..a5b85a2050 --- /dev/null +++ b/java/systests/etc/config-systests.json @@ -0,0 +1,64 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +{ + "name": "QpidBroker", + "defaultAuthenticationProvider" : "plain", + "defaultVirtualHost" : "test", + "keyStorePath": "${QPID_HOME}/../test-profiles/test_resources/ssl/java_broker_keystore.jks", + "keyStorePassword": "password", + "trustStorePath": "${QPID_HOME}/../test-profiles/test_resources/ssl/java_client_truststore.jks", + "trustStorePassword": "password", + "authenticationproviders" : [ { + "name" : "plain", + "authenticationProviderType" : "PlainPasswordFileAuthenticationProvider", + "path" : "${QPID_HOME}/etc/passwd" + } ], + "ports" : [ { + "name" : "amqp", + "port" : "${test.port}" + }, { + "name" : "http", + "port" : "${test.hport}", + "protocols" : [ "HTTP" ] + }, { + "name" : "rmi", + "port" : "${test.mport}", + "protocols" : [ "RMI" ] + }, { + "name" : "jmx", + "port" : "${test.cport}", + "protocols" : [ "JMX_RMI" ] + }], + "virtualhosts" : [ { + "name" : "test", + "configPath" : "${broker.virtualhosts-config}" + } ] + /* +, + "plugins" : [ { + "pluginType" : "MANAGEMENT-HTTP", + "name" : "httpManagement" + }, { + "pluginType" : "MANAGEMENT-JMX", + "name" : "jmxManagement" + } ] + */ +} \ No newline at end of file diff --git a/java/systests/etc/groups-systests b/java/systests/etc/groups-systests new file mode 100644 index 0000000000..e3912ece99 --- /dev/null +++ b/java/systests/etc/groups-systests @@ -0,0 +1,29 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# +# To define a group, use the format: +# +# .users=,,..., +# + +messaging-users.users=guest,client,server +administrators.users=admin +webadmins.users=webadmin + diff --git a/java/systests/etc/virtualhosts-systests-bdb-settings.xml b/java/systests/etc/virtualhosts-systests-bdb-settings.xml index ce16523f13..350f05c178 100644 --- a/java/systests/etc/virtualhosts-systests-bdb-settings.xml +++ b/java/systests/etc/virtualhosts-systests-bdb-settings.xml @@ -20,37 +20,13 @@ - --> - ${QPID_WORK} - - - localhost - - - org.apache.qpid.server.store.berkeleydb.BDBMessageStore - ${work}/bdbstore/localhost-store - - - - - - development - - - org.apache.qpid.server.store.berkeleydb.BDBMessageStore - ${work}/bdbstore/development-store - - - - test org.apache.qpid.server.store.berkeleydb.BDBMessageStore - ${work}/bdbstore/test-store + ${QPID_WORK}/test-store - - diff --git a/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml b/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml index 74189ad5e9..4e28f6d330 100644 --- a/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml +++ b/java/systests/etc/virtualhosts-systests-derby-mem-settings.xml @@ -20,35 +20,12 @@ - --> - ${QPID_HOME}/virtualhosts - test - - - - - org.apache.qpid.server.store.derby.DerbyMessageStoreFactory - :memory: - - - - - - - - org.apache.qpid.server.store.derby.DerbyMessageStoreFactory - :memory: - - - - - org.apache.qpid.server.store.derby.DerbyMessageStoreFactory + org.apache.qpid.server.store.derby.DerbyMessageStore :memory: - - diff --git a/java/systests/etc/virtualhosts-systests-derby-settings.xml b/java/systests/etc/virtualhosts-systests-derby-settings.xml index 08a40ca812..f9cc3d2336 100644 --- a/java/systests/etc/virtualhosts-systests-derby-settings.xml +++ b/java/systests/etc/virtualhosts-systests-derby-settings.xml @@ -20,35 +20,12 @@ - --> - ${QPID_HOME}/virtualhosts - test - - - - - org.apache.qpid.server.store.derby.DerbyMessageStore - ${QPID_WORK}/derbyDB/localhost-store - - - - - - - - org.apache.qpid.server.store.derby.DerbyMessageStore - ${QPID_WORK}/derbyDB/development-store - - - - org.apache.qpid.server.store.derby.DerbyMessageStore - ${QPID_WORK}/derbyDB/test-store + ${QPID_WORK}/test-store - - diff --git a/java/systests/etc/virtualhosts-systests-settings.xml b/java/systests/etc/virtualhosts-systests-settings.xml index 0ec16b31ef..5d4ec28b71 100644 --- a/java/systests/etc/virtualhosts-systests-settings.xml +++ b/java/systests/etc/virtualhosts-systests-settings.xml @@ -21,137 +21,12 @@ --> test - - localhost - - - org.apache.qpid.server.store.MemoryMessageStore - - - - 2 - 20000 - - - - - direct - test.direct - true - - - topic - test.topic - - - - amq.direct - 4235264 - - 2117632 - - 600000 - - 50 - - - - queue - - - ping - - - test-queue - - test.direct - true - - - - test-ping - - test.direct - - - - - - - - - - development - - - org.apache.qpid.server.store.MemoryMessageStore - - - - 30000 - 50 - - queue - - amq.direct - 4235264 - - 2117632 - - 600000 - - - - - ping - - amq.direct - 4235264 - - 2117632 - - 600000 - - - - - - test org.apache.qpid.server.store.MemoryMessageStore - - - 30000 - 50 - - queue - - amq.direct - 4235264 - - 2117632 - - 600000 - - - - - ping - - amq.direct - 4235264 - - 2117632 - - 600000 - - - - diff --git a/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java index 6655202067..3025414e4a 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/AMQQueueDeferredOrderingTest.java @@ -27,7 +27,6 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.test.utils.QpidBrokerTestCase; import javax.jms.Connection; -import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; @@ -72,10 +71,11 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase for (int i = start; i < end && !interrupted(); i++) { producer.send(session.createTextMessage(Integer.toString(i))); + ((AMQSession)session).sync(); } this._logger.info("Sent " + (end - start) + " messages"); } - catch (JMSException e) + catch (Exception e) { throw new RuntimeException(e); } @@ -101,7 +101,7 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase con.start(); } - public void testPausedOrder() throws Exception + public void testMessagesSentByTwoThreadsAreDeliveredInOrder() throws Exception { // Setup initial messages @@ -121,9 +121,9 @@ public class AMQQueueDeferredOrderingTest extends QpidBrokerTestCase for (int i = 0; i < numMessages; i++) { Message msg = consumer.receive(3000); - assertNotNull("Message should not be null", msg); - assertTrue("Message should be a text message", msg instanceof TextMessage); - assertEquals("Message content does not match expected", Integer.toString(i), ((TextMessage) msg).getText()); + assertNotNull("Message " + i + " should not be null", msg); + assertTrue("Message " + i + " should be a text message", msg instanceof TextMessage); + assertEquals("Message content " + i + "does not match expected", Integer.toString(i), ((TextMessage) msg).getText()); } } diff --git a/java/systests/src/main/java/org/apache/qpid/client/HeartbeatTest.java b/java/systests/src/main/java/org/apache/qpid/client/HeartbeatTest.java new file mode 100644 index 0000000000..0e01bda8d0 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/client/HeartbeatTest.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.client; + +import javax.jms.Destination; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class HeartbeatTest extends QpidBrokerTestCase +{ + public void testHeartbeats() throws Exception + { + setTestSystemProperty("amqj.heartbeat.delay", "1"); + AMQConnection conn = (AMQConnection) getConnection(); + TestListener listener = new TestListener(); + conn.setHeartbeatListener(listener); + conn.start(); + + Thread.sleep(2500); + + assertTrue("Too few heartbeats received: "+listener._heartbeatsReceived+" (expected at least 2)", listener._heartbeatsReceived>=2); + assertTrue("Too few heartbeats sent "+listener._heartbeatsSent+" (expected at least 2)", listener._heartbeatsSent>=2); + + conn.close(); + } + + public void testNoHeartbeats() throws Exception + { + setTestSystemProperty("amqj.heartbeat.delay", "0"); + AMQConnection conn = (AMQConnection) getConnection(); + TestListener listener = new TestListener(); + conn.setHeartbeatListener(listener); + conn.start(); + + Thread.sleep(2500); + + assertEquals("Heartbeats unexpectedly received", 0, listener._heartbeatsReceived); + assertEquals("Heartbeats unexpectedly sent ", 0, listener._heartbeatsSent); + + conn.close(); + } + + public void testReadOnlyConnectionHeartbeats() throws Exception + { + setTestSystemProperty("amqj.heartbeat.delay","1"); + AMQConnection receiveConn = (AMQConnection) getConnection(); + AMQConnection sendConn = (AMQConnection) getConnection(); + Destination destination = getTestQueue(); + TestListener receiveListener = new TestListener(); + TestListener sendListener = new TestListener(); + + + Session receiveSession = receiveConn.createSession(false, Session.CLIENT_ACKNOWLEDGE); + Session senderSession = sendConn.createSession(false, Session.CLIENT_ACKNOWLEDGE); + + MessageConsumer consumer = receiveSession.createConsumer(destination); + MessageProducer producer = senderSession.createProducer(destination); + + receiveConn.setHeartbeatListener(receiveListener); + sendConn.setHeartbeatListener(sendListener); + receiveConn.start(); + + for(int i = 0; i < 5; i++) + { + producer.send(senderSession.createTextMessage("Msg " + i)); + Thread.sleep(500); + assertNotNull("Expected to received message", consumer.receive(500)); + } + + + + assertTrue("Too few heartbeats sent "+receiveListener._heartbeatsSent+" (expected at least 2)", receiveListener._heartbeatsSent>=2); + assertEquals("Unexpected sent at the sender: ",0,sendListener._heartbeatsSent); + + assertTrue("Too few heartbeats received at the sender "+sendListener._heartbeatsReceived+" (expected at least 2)", sendListener._heartbeatsReceived>=2); + assertEquals("Unexpected received at the receiver: ",0,receiveListener._heartbeatsReceived); + + receiveConn.close(); + sendConn.close(); + } + + private class TestListener implements HeartbeatListener + { + int _heartbeatsReceived; + int _heartbeatsSent; + @Override + public void heartbeatReceived() + { + _heartbeatsReceived++; + } + + @Override + public void heartbeatSent() + { + _heartbeatsSent++; + } + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java b/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java index 4b766864b4..4f8a6ee54a 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java @@ -25,11 +25,12 @@ import org.apache.qpid.client.AMQSession; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionListener; -import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.jms.FailoverPolicy; import org.apache.qpid.test.utils.FailoverBaseCase; +import org.apache.qpid.url.URLSyntaxException; import javax.jms.Connection; +import javax.jms.ConnectionFactory; import javax.jms.Destination; import javax.jms.ExceptionListener; import javax.jms.JMSException; @@ -929,18 +930,22 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio return queue; } - private AMQConnection createConnectionWithFailover() throws NamingException, JMSException + private AMQConnection createConnectionWithFailover() throws NamingException, JMSException, URLSyntaxException { - AMQConnection connection; - AMQConnectionFactory connectionFactory = (AMQConnectionFactory)getConnectionFactory("default"); - ConnectionURL connectionURL = connectionFactory.getConnectionURL(); - connectionURL.setOption(ConnectionURL.OPTIONS_FAILOVER, "singlebroker"); - connectionURL.setOption(ConnectionURL.OPTIONS_FAILOVER_CYCLE, "2"); - BrokerDetails details = connectionURL.getBrokerDetails(0); - details.setProperty(BrokerDetails.OPTIONS_RETRY, "200"); - details.setProperty(BrokerDetails.OPTIONS_CONNECT_DELAY, "1000"); + BrokerDetails origBrokerDetails = ((AMQConnectionFactory) getConnectionFactory("default")).getConnectionURL().getBrokerDetails(0); - connection = (AMQConnection)connectionFactory.createConnection("admin", "admin"); + String retries = "200"; + String connectdelay = "1000"; + String cycleCount = "2"; + + String newUrlFormat="amqp://username:password@clientid/test?brokerlist=" + + "'tcp://%s:%s?retries='%s'&connectdelay='%s''&failover='singlebroker?cyclecount='%s''"; + + String newUrl = String.format(newUrlFormat, origBrokerDetails.getHost(), origBrokerDetails.getPort(), + retries, connectdelay, cycleCount); + + ConnectionFactory connectionFactory = new AMQConnectionFactory(newUrl); + AMQConnection connection = (AMQConnection) connectionFactory.createConnection("admin", "admin"); connection.setConnectionListener(this); return connection; } @@ -1313,7 +1318,7 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio * @param acknowledgeMode session acknowledge mode * @throws JMSException */ - private void sessionCloseWhileFailoverImpl(int acknowledgeMode) throws JMSException + private void sessionCloseWhileFailoverImpl(int acknowledgeMode) throws Exception { initDelayedFailover(acknowledgeMode); @@ -1324,9 +1329,14 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio failBroker(getFailingPort()); + // wait until failover is started + _failoverStarted.await(5, TimeUnit.SECONDS); + // test whether session#close blocks while failover is in progress _consumerSession.close(); + assertTrue("Failover has not completed yet but session was closed", _failoverComplete.await(5, TimeUnit.SECONDS)); + assertFailoverException(); } @@ -1360,10 +1370,8 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio * @param acknowledgeMode session acknowledge mode * @throws JMSException */ - private void browserCloseWhileFailoverImpl(int acknowledgeMode) throws JMSException + private void browserCloseWhileFailoverImpl(int acknowledgeMode) throws Exception { - setDelayedFailoverPolicy(); - QueueBrowser browser = prepareQueueBrowser(acknowledgeMode); @SuppressWarnings("unchecked") @@ -1373,8 +1381,13 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio failBroker(getFailingPort()); + // wait until failover is started + _failoverStarted.await(5, TimeUnit.SECONDS); + browser.close(); + assertTrue("Failover has not completed yet but browser was closed", _failoverComplete.await(5, TimeUnit.SECONDS)); + assertFailoverException(); } @@ -1402,5 +1415,11 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio ((AMQConnection) _connection).setFailoverPolicy(failoverPolicy); return failoverPolicy; } - + + @Override + public void failBroker(int port) + { + killBroker(port); + } + } diff --git a/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java b/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java new file mode 100644 index 0000000000..a0fd093bfe --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java @@ -0,0 +1,285 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.client.failover; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.jms.Connection; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.log4j.Logger; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQConnectionURL; +import org.apache.qpid.jms.ConnectionListener; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.test.utils.TestUtils; +import org.apache.qpid.util.FileUtils; + +public class MultipleBrokersFailoverTest extends QpidBrokerTestCase implements ConnectionListener +{ + private static final Logger _logger = Logger.getLogger(MultipleBrokersFailoverTest.class); + + private static final String FAILOVER_VIRTUAL_HOST = "failover"; + private static final String NON_FAILOVER_VIRTUAL_HOST = "nonfailover"; + private static final String BROKER_PORTION_FORMAT = "tcp://localhost:%d?connectdelay='%d',retries='%d'"; + private static final int FAILOVER_RETRIES = 1; + private static final int FAILOVER_CONNECTDELAY = 1000; + private int[] _brokerPorts; + private AMQConnectionURL _connectionURL; + private Connection _connection; + private CountDownLatch _failoverComplete; + private CountDownLatch _failoverStarted; + private Session _consumerSession; + private Destination _destination; + private MessageConsumer _consumer; + private Session _producerSession; + private MessageProducer _producer; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + int numBrokers = 4; + int port = findFreePort(); + _brokerPorts = new int[numBrokers]; + + // we need to create 4 brokers: + // 1st broker will be running in test JVM and will not have failover host (only tcp connection will established, amqp connection will be closed) + // 2d broker will be spawn in separate JVM and should have a failover host (amqp connection should be established) + // 3d broker will be spawn in separate JVM and should not have a failover host (only tcp connection will established, amqp connection will be closed) + // 4d broker will be spawn in separate JVM and should have a failover host (amqp connection should be established) + + // the test should connect to the second broker first and fail over to the forth broker + // after unsuccessful try to establish the connection to the 3d broker + for (int i = 0; i < numBrokers; i++) + { + if (i > 0) + { + port = getNextAvailable(port + 1); + } + _brokerPorts[i] = port; + + createBrokerConfiguration(port); + String host = null; + if (i == 1 || i == _brokerPorts.length - 1) + { + host = FAILOVER_VIRTUAL_HOST; + } + else + { + host = NON_FAILOVER_VIRTUAL_HOST; + } + createTestVirtualHost(port, host); + + startBroker(port); + revertSystemProperties(); + } + + _connectionURL = new AMQConnectionURL(generateUrlString(numBrokers)); + + _connection = getConnection(_connectionURL); + ((AMQConnection) _connection).setConnectionListener(this); + _failoverComplete = new CountDownLatch(1); + _failoverStarted = new CountDownLatch(1); + } + + public void startBroker() throws Exception + { + // noop, prevent the broker startup in super.setUp() + } + + private String generateUrlString(int numBrokers) + { + String baseString = "amqp://guest:guest@test/" + FAILOVER_VIRTUAL_HOST + + "?&failover='roundrobin?cyclecount='1''&brokerlist='"; + StringBuffer buffer = new StringBuffer(baseString); + + for(int i = 0; i< numBrokers ; i++) + { + if(i != 0) + { + buffer.append(";"); + } + + String broker = String.format(BROKER_PORTION_FORMAT, _brokerPorts[i], + FAILOVER_CONNECTDELAY, FAILOVER_RETRIES); + buffer.append(broker); + } + buffer.append("'"); + + return buffer.toString(); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + for (int i = 0; i < _brokerPorts.length; i++) + { + if (_brokerPorts[i] > 0) + { + stopBrokerSafely(_brokerPorts[i]); + FileUtils.deleteDirectory(System.getProperty("QPID_WORK") + "/" + getFailingPort()); + } + } + + } + } + + + public void testFailoverOnBrokerKill() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + assertConnectionPort(_brokerPorts[1]); + + assertSendReceive(0); + + killBroker(_brokerPorts[1]); + + awaitForFailoverCompletion(FAILOVER_CONNECTDELAY * _brokerPorts.length * 2); + assertEquals("Failover is not started as expected", 0, _failoverStarted.getCount()); + + assertSendReceive(2); + assertConnectionPort(_brokerPorts[_brokerPorts.length - 1]); + } + + public void testFailoverOnBrokerStop() throws Exception + { + init(Session.SESSION_TRANSACTED, true); + assertConnectionPort(_brokerPorts[1]); + + assertSendReceive(0); + + stopBroker(_brokerPorts[1]); + + awaitForFailoverCompletion(FAILOVER_CONNECTDELAY * _brokerPorts.length * 2); + assertEquals("Failover is not started as expected", 0, _failoverStarted.getCount()); + + assertSendReceive(1); + assertConnectionPort(_brokerPorts[_brokerPorts.length - 1]); + } + + private void assertConnectionPort(int brokerPort) + { + int connectionPort = ((AMQConnection)_connection).getActiveBrokerDetails().getPort(); + assertEquals("Unexpected broker port", brokerPort, connectionPort); + } + + private void assertSendReceive(int index) throws JMSException + { + Message message = createNextMessage(_producerSession, index); + _producer.send(message); + if (_producerSession.getTransacted()) + { + _producerSession.commit(); + } + Message receivedMessage = _consumer.receive(1000l); + assertReceivedMessage(receivedMessage, index); + if (_consumerSession.getTransacted()) + { + _consumerSession.commit(); + } + } + + private void awaitForFailoverCompletion(long delay) + { + _logger.info("Awaiting Failover completion.."); + try + { + if (!_failoverComplete.await(delay, TimeUnit.MILLISECONDS)) + { + _logger.warn("Test thread stack:\n\n" + TestUtils.dumpThreads()); + fail("Failover did not complete"); + } + } + catch (InterruptedException e) + { + fail("Test was interrupted:" + e.getMessage()); + } + } + + private void assertReceivedMessage(Message receivedMessage, int messageIndex) + { + assertNotNull("Expected message [" + messageIndex + "] is not received!", receivedMessage); + assertTrue( + "Failure to receive message [" + messageIndex + "], expected TextMessage but received " + receivedMessage, + receivedMessage instanceof TextMessage); + } + + private void init(int acknowledgeMode, boolean startConnection) throws JMSException + { + boolean isTransacted = acknowledgeMode == Session.SESSION_TRANSACTED ? true : false; + + _consumerSession = _connection.createSession(isTransacted, acknowledgeMode); + _destination = _consumerSession.createQueue(getTestQueueName()); + _consumer = _consumerSession.createConsumer(_destination); + + if (startConnection) + { + _connection.start(); + } + + _producerSession = _connection.createSession(isTransacted, acknowledgeMode); + _producer = _producerSession.createProducer(_destination); + + } + + @Override + public void bytesSent(long count) + { + } + + @Override + public void bytesReceived(long count) + { + } + + @Override + public boolean preFailover(boolean redirect) + { + _failoverStarted.countDown(); + return true; + } + + @Override + public boolean preResubscribe() + { + return true; + } + + @Override + public void failoverComplete() + { + _failoverComplete.countDown(); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java b/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java index 39689f5096..884e89fb65 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/ssl/SSLTest.java @@ -20,54 +20,55 @@ */ package org.apache.qpid.client.ssl; -import org.apache.qpid.client.AMQConnection; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.client.AMQTestConnection_0_10; +import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.transport.Connection; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import javax.jms.Connection; +import javax.jms.JMSException; import javax.jms.Session; import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; public class SSLTest extends QpidBrokerTestCase { - private static final String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks"; - private static final String KEYSTORE_PASSWORD = "password"; - private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks"; - private static final String TRUSTSTORE_PASSWORD = "password"; private static final String CERT_ALIAS_APP1 = "app1"; private static final String CERT_ALIAS_APP2 = "app2"; @Override protected void setUp() throws Exception { - if(isJavaBroker()) - { - setTestClientSystemProperty("profile.use_ssl", "true"); - setConfigurationProperty("connector.ssl.enabled", "true"); - setConfigurationProperty("connector.ssl.sslOnly", "true"); - setConfigurationProperty("connector.ssl.wantClientAuth", "true"); - } - - // set the ssl system properties - setSystemProperty("javax.net.ssl.keyStore", KEYSTORE); - setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); - setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); - setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); setSystemProperty("javax.net.debug", "ssl"); - super.setUp(); + + setSslStoreSystemProperties(); + + //We dont call super.setUp, the tests start the broker after deciding + //whether to run and then configuring it appropriately } public void testCreateSSLConnectionUsingConnectionURLParams() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { - // Clear the ssl system properties - setSystemProperty("javax.net.ssl.keyStore", null); - setSystemProperty("javax.net.ssl.keyStorePassword", null); - setSystemProperty("javax.net.ssl.trustStore", null); - setSystemProperty("javax.net.ssl.trustStorePassword", null); + clearSslStoreSystemProperties(); + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" + "?ssl='true'&ssl_verify_hostname='true'" + "&key_store='%s'&key_store_password='%s'" + @@ -76,24 +77,75 @@ public class SSLTest extends QpidBrokerTestCase url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT, KEYSTORE,KEYSTORE_PASSWORD,TRUSTSTORE,TRUSTSTORE_PASSWORD); - - AMQConnection con = new AMQConnection(url); + + Connection con = getConnection(new AMQConnectionURL(url)); assertNotNull("connection should be successful", con); Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); assertNotNull("create session should be successful", ssn); - } + } + } + + /** + * Create an SSL connection using the SSL system properties for the trust and key store, but using + * the {@link ConnectionURL} ssl='true' option to indicate use of SSL at a Connection level, + * without specifying anything at the {@link ConnectionURL#OPTIONS_BROKERLIST} level. + */ + public void testSslConnectionOption() throws Exception + { + if (shouldPerformTest()) + { + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); + + //Create URL enabling SSL at the connection rather than brokerlist level + String url = "amqp://guest:guest@test/?ssl='true'&brokerlist='tcp://localhost:%s'"; + url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT); + + Connection con = getConnection(new AMQConnectionURL(url)); + assertNotNull("connection should be successful", con); + Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); + assertNotNull("create session should be successful", ssn); + } + } + + /** + * Create an SSL connection using the SSL system properties for the trust and key store, but using + * the {@link ConnectionURL} ssl='true' option to indicate use of SSL at a Connection level, + * overriding the false setting at the {@link ConnectionURL#OPTIONS_BROKERLIST} level. + */ + public void testSslConnectionOptionOverridesBrokerlistOption() throws Exception + { + if (shouldPerformTest()) + { + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); + + //Create URL enabling SSL at the connection, overriding the false at the brokerlist level + String url = "amqp://guest:guest@test/?ssl='true'&brokerlist='tcp://localhost:%s?ssl='false''"; + url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT); + + Connection con = getConnection(new AMQConnectionURL(url)); + assertNotNull("connection should be successful", con); + Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); + assertNotNull("create session should be successful", ssn); + } } public void testCreateSSLConnectionUsingSystemProperties() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s?ssl='true''"; url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT); - AMQConnection con = new AMQConnection(url); + Connection con = getConnection(new AMQConnectionURL(url)); assertNotNull("connection should be successful", con); Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); assertNotNull("create session should be successful", ssn); @@ -102,14 +154,18 @@ public class SSLTest extends QpidBrokerTestCase public void testMultipleCertsInSingleStore() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (NEEDing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, true, false); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_cert_alias='" + CERT_ALIAS_APP1 + "''"; AMQTestConnection_0_10 con = new AMQTestConnection_0_10(url); - Connection transportCon = con.getConnection(); + org.apache.qpid.transport.Connection transportCon = con.getConnection(); String userID = transportCon.getSecurityLayer().getUserID(); assertEquals("The correct certificate was not choosen","app1@acme.org",userID); con.close(); @@ -126,65 +182,82 @@ public class SSLTest extends QpidBrokerTestCase } } - public void testVerifyHostNameWithIncorrectHostname() + public void testVerifyHostNameWithIncorrectHostname() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (WANTing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, false, true); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://127.0.0.1:" + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_verify_hostname='true''"; try { - AMQConnection con = new AMQConnection(url); + getConnection(new AMQConnectionURL(url)); fail("Hostname verification failed. No exception was thrown"); } catch (Exception e) { - ByteArrayOutputStream bout = new ByteArrayOutputStream(); - e.printStackTrace(new PrintStream(bout)); - String strace = bout.toString(); - assertTrue("Correct exception not thrown",strace.contains("SSL hostname verification failed")); + verifyExceptionCausesContains(e, "SSL hostname verification failed"); } - } } + + private void verifyExceptionCausesContains(Exception e, String expectedString) + { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(bout)); + String strace = bout.toString(); + assertTrue("Correct exception not thrown", strace.contains(expectedString)); + } public void testVerifyLocalHost() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (WANTing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, false, true); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:" + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_verify_hostname='true''"; - AMQConnection con = new AMQConnection(url); - assertNotNull("connection should have been created", con); + Connection con = getConnection(new AMQConnectionURL(url)); + assertNotNull("connection should have been created", con); } } public void testVerifyLocalHostLocalDomain() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { + //Start the broker (WANTing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, false, true); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost.localdomain:" + QpidBrokerTestCase.DEFAULT_SSL_PORT + "?ssl='true'&ssl_verify_hostname='true''"; - AMQConnection con = new AMQConnection(url); + Connection con = getConnection(new AMQConnectionURL(url)); assertNotNull("connection should have been created", con); } } public void testCreateSSLConnectionUsingConnectionURLParamsTrustStoreOnly() throws Exception { - if (Boolean.getBoolean("profile.use_ssl")) + if (shouldPerformTest()) { - // Clear the ssl system properties - setSystemProperty("javax.net.ssl.keyStore", null); - setSystemProperty("javax.net.ssl.keyStorePassword", null); - setSystemProperty("javax.net.ssl.trustStore", null); - setSystemProperty("javax.net.ssl.trustStorePassword", null); + clearSslStoreSystemProperties(); + + //Start the broker (WANTing client certificate authentication) + configureJavaBrokerIfNecessary(true, true, false, true); + super.setUp(); + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" + "?ssl='true'&ssl_verify_hostname='true'" + @@ -193,10 +266,122 @@ public class SSLTest extends QpidBrokerTestCase url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT, TRUSTSTORE,TRUSTSTORE_PASSWORD); - AMQConnection con = new AMQConnection(url); + Connection con = getConnection(new AMQConnectionURL(url)); assertNotNull("connection should be successful", con); Session ssn = con.createSession(false,Session.AUTO_ACKNOWLEDGE); assertNotNull("create session should be successful", ssn); } } + + /** + * Verifies that when the broker is configured to NEED client certificates, + * a client which doesn't supply one fails to connect. + */ + public void testClientCertMissingWhilstNeeding() throws Exception + { + missingClientCertWhileNeedingOrWantingTestImpl(true, false, false); + } + + /** + * Verifies that when the broker is configured to WANT client certificates, + * a client which doesn't supply one succeeds in connecting. + */ + public void testClientCertMissingWhilstWanting() throws Exception + { + missingClientCertWhileNeedingOrWantingTestImpl(false, true, true); + } + + /** + * Verifies that when the broker is configured to WANT and NEED client certificates + * that a client which doesn't supply one fails to connect. + */ + public void testClientCertMissingWhilstWantingAndNeeding() throws Exception + { + missingClientCertWhileNeedingOrWantingTestImpl(true, true, false); + } + + private void missingClientCertWhileNeedingOrWantingTestImpl(boolean needClientCerts, + boolean wantClientCerts, boolean shouldSucceed) throws Exception + { + if (shouldPerformTest()) + { + clearSslStoreSystemProperties(); + + //Start the broker + configureJavaBrokerIfNecessary(true, true, needClientCerts, wantClientCerts); + super.setUp(); + + String url = "amqp://guest:guest@test/?brokerlist='tcp://localhost:%s" + + "?ssl='true'&trust_store='%s'&trust_store_password='%s''"; + + url = String.format(url,QpidBrokerTestCase.DEFAULT_SSL_PORT,TRUSTSTORE,TRUSTSTORE_PASSWORD); + try + { + Connection con = getConnection(new AMQConnectionURL(url)); + if(!shouldSucceed) + { + fail("Connection succeeded, expected exception was not thrown"); + } + else + { + //Use the connection to verify it works + con.createSession(true, Session.SESSION_TRANSACTED); + } + } + catch(JMSException e) + { + if(shouldSucceed) + { + _logger.error("Caught unexpected exception",e); + fail("Connection failed, unexpected exception thrown"); + } + else + { + //expected + verifyExceptionCausesContains(e, "Caused by: javax.net.ssl.SSLException:"); + } + } + } + } + + private boolean shouldPerformTest() + { + // We run the SSL tests on all the Java broker profiles + if(isJavaBroker()) + { + setTestClientSystemProperty(PROFILE_USE_SSL, "true"); + } + + return Boolean.getBoolean(PROFILE_USE_SSL); + } + + private void configureJavaBrokerIfNecessary(boolean sslEnabled, boolean sslOnly, boolean needClientAuth, boolean wantClientAuth) throws ConfigurationException + { + if(isJavaBroker()) + { + Map sslPortAttributes = new HashMap(); + sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); + sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT); + sslPortAttributes.put(Port.NEED_CLIENT_AUTH, needClientAuth); + sslPortAttributes.put(Port.WANT_CLIENT_AUTH, wantClientAuth); + sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT); + getBrokerConfiguration().addPortConfiguration(sslPortAttributes); + } + } + + private void setSslStoreSystemProperties() + { + setSystemProperty("javax.net.ssl.keyStore", KEYSTORE); + setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); + setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); + setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); + } + + private void clearSslStoreSystemProperties() + { + setSystemProperty("javax.net.ssl.keyStore", null); + setSystemProperty("javax.net.ssl.keyStorePassword", null); + setSystemProperty("javax.net.ssl.trustStore", null); + setSystemProperty("javax.net.ssl.trustStorePassword", null); + } } diff --git a/java/systests/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxyTest.java b/java/systests/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxyTest.java new file mode 100644 index 0000000000..80001099a8 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/ra/admin/QpidConnectionFactoryProxyTest.java @@ -0,0 +1,120 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.ra.admin; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.naming.NamingException; +import javax.jms.QueueConnection; +import javax.jms.QueueConnectionFactory; +import javax.naming.Reference; +import javax.naming.Referenceable; +import javax.naming.spi.ObjectFactory; +import javax.jms.TopicConnection; +import javax.jms.TopicConnectionFactory; + +import junit.framework.TestCase; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +public class QpidConnectionFactoryProxyTest extends QpidBrokerTestCase +{ + private static final String BROKER_PORT = "15672"; + + private static final String URL = "amqp://guest:guest@client/test?brokerlist='tcp://localhost:" + BROKER_PORT + "?sasl_mechs='PLAIN''"; + + public void testQueueConnectionFactory() throws Exception + { + QueueConnectionFactory cf = null; + QueueConnection c = null; + + try + { + cf = new QpidConnectionFactoryProxy(); + ((QpidConnectionFactoryProxy)cf).setConnectionURL(URL); + c = cf.createQueueConnection(); + assertTrue(c instanceof QueueConnection); + + } + finally + { + if(c != null) + { + c.close(); + } + } + } + + public void testTopicConnectionFactory() throws Exception + { + TopicConnectionFactory cf = null; + TopicConnection c = null; + + try + { + cf = new QpidConnectionFactoryProxy(); + ((QpidConnectionFactoryProxy)cf).setConnectionURL(URL); + c = cf.createTopicConnection(); + assertTrue(c instanceof TopicConnection); + + } + finally + { + if(c != null) + { + c.close(); + } + } + try + { + + } + finally + { + + } + } + + public void testConnectionFactory() throws Exception + { + ConnectionFactory cf = null; + Connection c = null; + + try + { + cf = new QpidConnectionFactoryProxy(); + ((QpidConnectionFactoryProxy)cf).setConnectionURL(URL); + c = cf.createConnection(); + assertTrue(c instanceof Connection); + + } + finally + { + if(c != null) + { + c.close(); + } + + } + } +} + diff --git a/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java b/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java index 9f3994fc91..eba2a638c0 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/BrokerStartupTest.java @@ -30,6 +30,7 @@ import org.apache.qpid.util.LogMonitor; import javax.jms.Connection; import javax.jms.Queue; import javax.jms.Session; +import java.io.File; import java.util.List; /** @@ -72,10 +73,7 @@ public class BrokerStartupTest extends AbstractTestLogging if (isJavaBroker() && isExternalBroker() && !isInternalBroker()) { //Remove test Log4j config from the commandline - _brokerCommand = _brokerCommand.substring(0, _brokerCommand.indexOf("-l")); - - // Add an invalid value - _brokerCommand += " -l invalid"; + setBrokerCommandLog4JFile(new File("invalid file")); // The broker has a built in default log4j configuration set up // so if the the broker cannot load the -l value it will use default @@ -145,4 +143,4 @@ public class BrokerStartupTest extends AbstractTestLogging } } -} \ No newline at end of file +} diff --git a/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java b/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java index e8d72c13bd..23a00431d1 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/SupportedProtocolVersionsTest.java @@ -23,13 +23,17 @@ package org.apache.qpid.server; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.adapter.PortFactoryTest; import org.apache.qpid.test.utils.QpidBrokerTestCase; /** * Tests to validate it is possible to disable support for particular protocol * versions entirely, rather than selectively excluding them on particular ports, * and it is possible to configure the reply to an unsupported protocol initiation. + *

+ * Protocol exclusion/inclusion are unit tested as part of {@link PortFactoryTest} */ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase { @@ -41,8 +45,8 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase private void clearProtocolSupportManipulations() { //Remove the QBTC provided protocol manipulations, giving only the protocols which default to enabled - setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_EXCLUDES, null); - setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_INCLUDES, null); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, null); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES, null); } /** @@ -87,8 +91,8 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase clearProtocolSupportManipulations(); //disable 0-10 and 1-0 support - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, + Protocol.AMQP_1_0 + "," + Protocol.AMQP_0_10); super.setUp(); @@ -100,52 +104,14 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase connection.close(); } - public void testDisabling091and010and10() throws Exception - { - clearProtocolSupportManipulations(); - - //disable 0-91 and 0-10 and 1-0 support - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP091ENABLED, "false"); - - super.setUp(); - - //Verify initially requesting a 0-10 connection now negotiates a 0-9 - //connection as the broker should reply with its highest supported protocol - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - AMQConnection connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_9, connection.getProtocolVersion()); - connection.close(); - } - - public void testDisabling09and091and010and10() throws Exception - { - clearProtocolSupportManipulations(); - - //disable 0-9, 0-91, 0-10 and 1-0 support - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP09ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP091ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); - - super.setUp(); - - //Verify initially requesting a 0-10 connection now negotiates a 0-8 - //connection as the broker should reply with its highest supported protocol - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - AMQConnection connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v8_0, connection.getProtocolVersion()); - connection.close(); - } - public void testConfiguringReplyingToUnsupported010ProtocolInitiationWith09insteadOf091() throws Exception { clearProtocolSupportManipulations(); //disable 0-10 support, and set the default unsupported protocol initiation reply to 0-9 - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP_SUPPORTED_REPLY, "v0_9"); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES, + Protocol.AMQP_1_0 + "," + Protocol.AMQP_0_10); + setSystemProperty(BrokerProperties.PROPERTY_DEFAULT_SUPPORTED_PROTOCOL_REPLY, "v0_9"); super.setUp(); @@ -164,71 +130,5 @@ public class SupportedProtocolVersionsTest extends QpidBrokerTestCase connection.close(); } - public void testProtocolInclusionThroughQBTCSystemPropertiesOverridesProtocolExclusion() throws Exception - { - testProtocolInclusionOverridesProtocolExclusion(false); - } - - public void testProtocolInclusionThroughConfigOverridesProtocolExclusion() throws Exception - { - testProtocolInclusionOverridesProtocolExclusion(true); - } - - private void testProtocolInclusionOverridesProtocolExclusion(boolean useConfig) throws Exception - { - clearProtocolSupportManipulations(); - - //selectively exclude 0-10 and 1-0 on the test port - setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_EXCLUDES,"--exclude-0-10 @PORT --exclude-1-0 @PORT"); - - super.setUp(); - - //Verify initially requesting a 0-10 connection negotiates a 0-9-1 connection - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - AMQConnection connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_91, connection.getProtocolVersion()); - connection.close(); - - stopBroker(); - - if(useConfig) - { - //selectively include 0-10 support again on the test port through config - setConfigurationProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, String.valueOf(getPort())); - } - else - { - //selectively include 0-10 support again on the test port through QBTC sys props - setTestSystemProperty(QpidBrokerTestCase.BROKER_PROTOCOL_INCLUDES,"--include-0-10 @PORT"); - } - - startBroker(); - - //Verify requesting a 0-10 connection now returns one - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_10, connection.getProtocolVersion()); - connection.close(); - } - - public void testProtocolInclusionOverridesProtocolDisabling() throws Exception - { - clearProtocolSupportManipulations(); - - //disable 0-10 and 1-0 - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP010ENABLED, "false"); - setConfigurationProperty(ServerConfiguration.CONNECTOR_AMQP10ENABLED, "false"); - - //selectively include 0-10 support again on the test port - setConfigurationProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, String.valueOf(getPort())); - - super.setUp(); - - //Verify initially requesting a 0-10 connection still works - setTestClientSystemProperty(ClientProperties.AMQP_VERSION, "0-10"); - AMQConnection connection = (AMQConnection) getConnection(); - assertEquals("Unexpected protocol version in use", ProtocolVersion.v0_10, connection.getProtocolVersion()); - connection.close(); - } } \ No newline at end of file diff --git a/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java b/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java deleted file mode 100644 index 6f54a56e93..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/configuration/ServerConfigurationFileTest.java +++ /dev/null @@ -1,75 +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.configuration; - -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -/** - * This system test ensures that when loading our default system-test - * configuration file the configuration is correctly loaded. - * - * All configuration values should be set in the systest config file so that - * the ability to load them can be validated. - */ -public class ServerConfigurationFileTest extends QpidBrokerTestCase -{ - private ServerConfiguration _serverConfig; - - public void setUp() throws ConfigurationException - { - if (!_configFile.exists()) - { - fail("Unable to test without config file:" + _configFile); - } - - saveTestConfiguration(); - saveTestVirtualhosts(); - - _serverConfig = new ServerConfiguration(_configFile); - } - - /** - * This helper method ensures that when we attempt to read a value that is - * set in the configuration file we do actualy read a value and not - * simply get a defaulted value from the ServerConfiguration.get*() methods. - * - * @param property the propert to test - */ - private void validatePropertyDefinedInFile(String property) - { - //Verify that we are not just picking up the the default value from the getBoolean - assertNotNull("The value set in the configuration file is not being read for property:" + property, - _serverConfig.getConfig().getProperty(property)); - } - - public void testStatusUpdates() throws ConfigurationException - { - validatePropertyDefinedInFile(ServerConfiguration.STATUS_UPDATES); - } - - public void testLocale() throws ConfigurationException - { - validatePropertyDefinedInFile(ServerConfiguration.ADVANCED_LOCALE); - } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java b/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java deleted file mode 100644 index 87a53a0765..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/server/failure/HeapExhaustion.java +++ /dev/null @@ -1,237 +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.failure; - -import junit.framework.TestCase; -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.client.failover.FailoverException; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.test.utils.QpidClientConnectionHelper; - -import javax.jms.DeliveryMode; -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 QpidClientConnectionHelper 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 QpidClientConnectionHelper(BROKER); - conn.setVirtualHost(vhost); - - try - { - conn.connect(); - } catch (JMSException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - // 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 testUntilFailureTransient() throws Exception - { - int copies = 0; - int total = 0; - String payload = hundredK; - int size = payload.getBytes().length; - while (true) - { - conn.put(queue, payload, 1, DeliveryMode.NON_PERSISTENT); - copies++; - total += size; - System.out.println("put copy " + copies + " OK for total bytes: " + total); - } - } - - /** - * PUT at lower rate (5 per second) until failure - * - * @throws Exception on error - */ - public void testUntilFailureWithDelaysTransient() throws Exception - { - int copies = 0; - int total = 0; - String payload = hundredK; - int size = payload.getBytes().length; - while (true) - { - conn.put(queue, payload, 1, DeliveryMode.NON_PERSISTENT); - copies++; - total += size; - System.out.println("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.testUntilFailureTransient(); - } - 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.testUntilFailureWithDelaysTransient(); - } - 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/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java index b666b1f424..84017b6850 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AbstractTestLogging.java @@ -20,12 +20,7 @@ */ package org.apache.qpid.server.logging; -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.util.LogMonitor; @@ -47,8 +42,6 @@ public class AbstractTestLogging extends QpidBrokerTestCase public static final String TEST_LOG_PREFIX = "MESSAGE"; protected LogMonitor _monitor; - private InternalBrokerBaseCase _configLoader; - @Override public void setUp() throws Exception { @@ -58,32 +51,6 @@ public class AbstractTestLogging extends QpidBrokerTestCase _monitor = new LogMonitor(_outputFile); } - protected ServerConfiguration getServerConfig() throws ConfigurationException - { - ServerConfiguration _serverConfiguration; - if (isExternalBroker()) - { - _serverConfiguration = new ServerConfiguration(_configFile) - { - @Override - public void initialise() throws ConfigurationException - { - //Overriding initialise to only setup the vhosts and not - //perform the ConfigurationPlugin setup, removing need for - //an ApplicationRegistry to be loaded. - setupVirtualHosts(getConfig()); - } - }; - _serverConfiguration.initialise(); - } - else - { - _serverConfiguration = ApplicationRegistry.getInstance().getConfiguration(); - } - - return _serverConfiguration; - } - protected void setLogMessagePrefix() { //set the message prefix to facilitate scraping from the munged test output. @@ -94,10 +61,6 @@ public class AbstractTestLogging extends QpidBrokerTestCase public void tearDown() throws Exception { _monitor.close(); - if (isExternalBroker() && _configLoader != null) - { - _configLoader.tearDown(); - } super.tearDown(); } @@ -159,7 +122,7 @@ public class AbstractTestLogging extends QpidBrokerTestCase } protected String fromMessage(String log) - { + {; int startSubject = log.indexOf("]") + 1; int start = log.indexOf("]", startSubject) + 1; diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java index 4b7b3f0cf0..37f960a65a 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java @@ -31,10 +31,10 @@ import java.util.List; /** * ACL version 2/3 file testing to verify that ACL actor logging works correctly. - * + * * This suite of tests validate that the AccessControl messages occur correctly * and according to the following format: - * + * *

  * ACL-1001 : Allowed Operation Object {PROPERTIES}
  * ACL-1002 : Denied Operation Object {PROPERTIES}
@@ -83,12 +83,12 @@ public class AccessControlLoggingTest extends AbstractTestLogging
         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         conn.start();
         ((AMQSession) sess).createQueue(new AMQShortString("allow"), false, false, false);
-        
+
         List matches = findMatches(ACL_LOG_PREFIX);
-        
+
         assertTrue("Should be no ACL log messages", matches.isEmpty());
     }
-    
+
     /**
      * Test that {@code allow-log} ACL entries log correctly.
      */
@@ -98,25 +98,25 @@ public class AccessControlLoggingTest extends AbstractTestLogging
         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         conn.start();
         ((AMQSession) sess).createQueue(new AMQShortString("allow-log"), false, false, false);
-        
+
         List matches = findMatches(ACL_LOG_PREFIX);
-        
+
         assertEquals("Should only be one ACL log message", 1, matches.size());
-        
+
         String log = getLogMessage(matches, 0);
         String actor = fromActor(log);
         String subject = fromSubject(log);
         String message = getMessageString(fromMessage(log));
-        
+
         validateMessageID(ACL_LOG_PREFIX + 1001, log);
-        
-        assertTrue("Actor should contain the user identity", actor.contains(USER));
+
+        assertTrue("Actor " + actor + " should contain the user identity: " + USER, actor.contains(USER));
         assertTrue("Subject should be empty", subject.length() == 0);
         assertTrue("Message should start with 'Allowed'", message.startsWith("Allowed"));
         assertTrue("Message should contain 'Create Queue'", message.contains("Create Queue"));
         assertTrue("Message should have contained the queue name", message.contains("allow-log"));
     }
-    
+
     /**
      * Test that {@code deny-log} ACL entries log correctly.
      */
@@ -134,25 +134,25 @@ public class AccessControlLoggingTest extends AbstractTestLogging
             // Denied, so exception thrown
             assertEquals("Expected ACCESS_REFUSED error code", AMQConstant.ACCESS_REFUSED, amqe.getErrorCode());
         }
-        
+
         List matches = findMatches(ACL_LOG_PREFIX);
-        
+
         assertEquals("Should only be one ACL log message", 1, matches.size());
-        
+
         String log = getLogMessage(matches, 0);
         String actor = fromActor(log);
         String subject = fromSubject(log);
         String message = getMessageString(fromMessage(log));
-        
+
         validateMessageID(ACL_LOG_PREFIX + 1002, log);
-        
-        assertTrue("Actor should contain the user identity", actor.contains(USER));
+
+        assertTrue("Actor " + actor + " should contain the user identity: " + USER, actor.contains(USER));
         assertTrue("Subject should be empty", subject.length() == 0);
         assertTrue("Message should start with 'Denied'", message.startsWith("Denied"));
         assertTrue("Message should contain 'Create Queue'", message.contains("Create Queue"));
         assertTrue("Message should have contained the queue name", message.contains("deny-log"));
     }
-    
+
     /**
      * Test that {@code deny} ACL entries do not log anything.
      */
@@ -170,9 +170,9 @@ public class AccessControlLoggingTest extends AbstractTestLogging
             // Denied, so exception thrown
             assertEquals("Expected ACCESS_REFUSED error code", AMQConstant.ACCESS_REFUSED, amqe.getErrorCode());
         }
-        
+
         List matches = findMatches(ACL_LOG_PREFIX);
-        
+
         assertTrue("Should be no ACL log messages", matches.isEmpty());
     }
 }
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java
index 02c41e14c0..68ec101245 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java
@@ -22,10 +22,6 @@ package org.apache.qpid.server.logging;
 
 import org.apache.qpid.client.AMQDestination;
 import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.framing.AMQShortString;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.util.FileUtils;
 
 import javax.jms.Connection;
 import javax.jms.Queue;
@@ -44,29 +40,19 @@ public class AlertingTest extends AbstractTestLogging
 
     public void setUp() throws Exception
     {
-        // Update the configuration to make our virtualhost Persistent.
-        makeVirtualHostPersistent(VIRTUALHOST);
-        setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "5000");
-
         _numMessages = 50;
 
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", String.valueOf(ALERT_LOG_WAIT_PERIOD));
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", String.valueOf(_numMessages));
+
         // Then we do the normal setup stuff like starting the broker, getting a connection etc.
         super.setUp();
 
         setupConnection();
     }
 
-    @Override
-    public void tearDown() throws Exception
-    {
-        // Ensure queue is clean for next run.
-        drainQueue(_destination);
-        super.tearDown();
-    }
-
-
     /**
-     * Create a new connection and ensure taht our destination queue is created
+     * Create a new connection and ensure that our destination queue is created
      * and bound.
      *
      * Note that the tests here that restart the broker rely on persistence.
@@ -102,20 +88,6 @@ public class AlertingTest extends AbstractTestLogging
         if (!waitForMessage(MESSAGE_COUNT_ALERT, ALERT_LOG_WAIT_PERIOD))
         {
             StringBuffer message = new StringBuffer("Could not find 'MESSAGE_COUNT_ALERT' in log file: " + _monitor.getMonitoredFile().getAbsolutePath());
-            message.append("\n");
-
-            // Add the current contents of the log file to test output
-            message.append(_monitor.readFile());
-
-            // Write the test config file to test output
-            message.append("Server configuration overrides in use:\n");
-            message.append(FileUtils.readFileAsString(getTestConfigFile()));
-
-            message.append("\nVirtualhost maxMessageCount:\n");
-            ServerConfiguration config = new ServerConfiguration(_configFile);
-            config.initialise();
-            message.append(config.getVirtualHostConfig(VIRTUALHOST).getMaximumMessageCount());
-
             fail(message.toString());
         }
     }
@@ -148,9 +120,6 @@ public class AlertingTest extends AbstractTestLogging
      * Test sends two messages to the broker then restarts the broker with new
      * configuration.
      *
-     * If the test is running inVM the test validates that the new configuration
-     * has been applied.
-     *
      * Validates that we only have two messages on the queue and then sends
      * enough messages to trigger the alert.
      *
@@ -172,31 +141,24 @@ public class AlertingTest extends AbstractTestLogging
         _monitor.markDiscardPoint();
 
         // Change max message count to 5, start broker and make sure that that's triggered at the right time
-        setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", "5");
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".queues.maximumMessageCount", "5");
 
         startBroker();
 
-        if (isInternalBroker())
-        {
-            assertEquals("Alert Max Msg Count is not correct", 5, ApplicationRegistry.getInstance().getVirtualHostRegistry().
-                    getVirtualHost(VIRTUALHOST).getQueueRegistry().getQueue(new AMQShortString(_destination.getQueueName())).
-                    getMaximumMessageCount());
-        }
-
         setupConnection();
 
         // Validate the queue depth is as expected
         long messageCount = ((AMQSession) _session).getQueueDepth((AMQDestination) _destination);
         assertEquals("Broker has invalid message count for test", 2, messageCount);
 
-        // Ensure the alert has not occured yet
+        // Ensure the alert has not occurred yet
         assertLoggingNotYetOccured(MESSAGE_COUNT_ALERT);
 
         // Trigger the new value
         sendMessage(_session, _destination, 3);
         _session.commit();
 
-        // Validate that the alert occured.
+        // Validate that the alert occurred.
         wasAlertFired();
     }
 }
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
index dee593b12b..c5f5e06ae1 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java
@@ -23,12 +23,20 @@ package org.apache.qpid.server.logging;
 import junit.framework.AssertionFailedError;
 
 import org.apache.qpid.server.BrokerOptions;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
 import org.apache.qpid.transport.ConnectionException;
 import org.apache.qpid.util.LogMonitor;
 
 import java.io.IOException;
 import java.net.Socket;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Broker Test Suite
@@ -47,6 +55,8 @@ import java.util.List;
  */
 public class BrokerLoggingTest extends AbstractTestLogging
 {
+    private static final String BROKER_MESSAGE_LOG_REG_EXP = ".*\\[\\w*\\] (BRK\\-\\d*) .*";
+    private static final Pattern BROKER_MESSAGE_LOG_PATTERN = Pattern.compile(BROKER_MESSAGE_LOG_REG_EXP);
     private static final String BRK_LOG_PREFIX = "BRK-";
 
     public void setUp() throws Exception
@@ -95,7 +105,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
             _monitor = new LogMonitor(_outputFile);
 
 
-            String configFilePath = _configFile.toString();
+            String configFilePath = getConfigPath();
 
             // Ensure we wait for TESTID to be logged
             waitAndFindMatches(TESTID);
@@ -118,8 +128,9 @@ public class BrokerLoggingTest extends AbstractTestLogging
                              1, results.size());
 
                 //3
-                assertTrue("Config file details not correctly logged",
-                           log.endsWith(configFilePath));
+                assertTrue("Config file details not correctly logged, got "
+                        + log + " but expected it to end with " + configFilePath,
+                        log.endsWith(configFilePath));
             }
             catch (AssertionFailedError afe)
             {
@@ -130,6 +141,11 @@ public class BrokerLoggingTest extends AbstractTestLogging
         }
     }
 
+    private String getConfigPath()
+    {
+        return getPathRelativeToWorkingDirectory(getTestConfigFile(DEFAULT_PORT));
+    }
+
     /**
      * Description:
      * On startup the broker must report correctly report the log4j file in use. This is important as it can help diagnose why logging messages are not being reported.
@@ -155,8 +171,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
         {
             String TESTID = "BRK-1007";
 
-            //Remove test Log4j config from the commandline
-            _brokerCommand = _brokerCommand.substring(0, _brokerCommand.indexOf("-l"));
+            _brokerCommandHelper.removeBrokerCommandLog4JFile();
 
             startBroker();
 
@@ -243,8 +258,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
         // This logging startup code only occurs when you run a Java broker
         if (isJavaBroker() && isExternalBroker())
         {
-            // Get custom -l value used during testing for the broker startup
-            String customLog4j = _brokerCommand.substring(_brokerCommand.indexOf("-l") + 2).trim();
+            String customLog4j = getBrokerCommandLog4JFile().getAbsolutePath();
 
             String TESTID = "BRK-1007";
 
@@ -293,8 +307,10 @@ public class BrokerLoggingTest extends AbstractTestLogging
                                  1, findMatches(TESTID).size());
 
                     //3
-                    assertTrue("Log4j file details not correctly logged:" + getMessageString(log),
-                               getMessageString(log).endsWith(customLog4j));
+                    String messageString = getMessageString(log);
+                    assertTrue("Log4j file details not correctly logged. Message '"
+                            + messageString + "' should contain '" +customLog4j + "'",
+                            messageString.endsWith(customLog4j));
 
                     validation = true;
                 }
@@ -442,10 +458,13 @@ public class BrokerLoggingTest extends AbstractTestLogging
                 {
                     String log = getLog(rawLog);
 
+                    // using custom method to get id as getMessageId() fails to correctly identify id
+                    // because of using brackets for protocols
+                    String id = getBrokerLogId(log);
                     // Ensure we do not have a BRK-1002 message
-                    if (!getMessageID(log).equals(TESTID))
+                    if (!id.equals(TESTID))
                     {
-                        if (getMessageID(log).equals("BRK-1001"))
+                        if (id.equals("BRK-1001"))
                         {
                             foundBRK1001 = true;
                         }
@@ -455,7 +474,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
                     assertTrue("BRK-1001 not logged before this message", foundBRK1001);
 
                     //1
-                    validateMessageID(TESTID, log);
+                    assertEquals("Incorrect message", TESTID, id);
 
                     //2
                     //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J)
@@ -465,7 +484,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
                     //3
                     String message = getMessageString(log);
                     assertTrue("Expected Listen log not correct" + message,
-                               message.endsWith("Listening on TCP port " + getPort()));
+                               message.endsWith("Listening on [TCP] port " + getPort()));
 
                     validation = true;
                 }
@@ -481,6 +500,16 @@ public class BrokerLoggingTest extends AbstractTestLogging
         }
     }
 
+    private String getBrokerLogId(String log)
+    {
+        Matcher m = BROKER_MESSAGE_LOG_PATTERN.matcher(log);
+        if (m.matches())
+        {
+            return m.group(1);
+        }
+        return getMessageID(log);
+    }
+
     /**
      * Description:
      * On startup the broker may listen on a number of ports and protocols. Each of these must be reported as they are made available.
@@ -498,8 +527,8 @@ public class BrokerLoggingTest extends AbstractTestLogging
      * 1. The BRK ID is correct
      * 2. This occurs after the BRK-1001 startup message
      * 3. With SSL enabled in the configuration two BRK-1002 will be printed (order is not specified)
-     * 1. One showing values TCP / 5672
-     * 2. One showing values TCP/SSL / 5672
+     * 1. One showing values [TCP] 5672
+     * 2. One showing values [SSL] 5671
      *
      * @throws Exception caused by broker startup
      */
@@ -512,12 +541,11 @@ public class BrokerLoggingTest extends AbstractTestLogging
             String TESTID = "BRK-1002";
 
             // Enable SSL on the connection
-            setConfigurationProperty("connector.ssl.enabled", "true");
-            setConfigurationProperty("connector.ssl.sslOnly", "false");
-            setConfigurationProperty("connector.ssl.keyStorePath", getConfigurationStringProperty("management.ssl.keyStorePath"));
-            setConfigurationProperty("connector.ssl.keyStorePassword", getConfigurationStringProperty("management.ssl.keyStorePassword"));
-
-            Integer sslPort = Integer.parseInt(getConfigurationStringProperty("connector.ssl.port"));
+            Map sslPortAttributes = new HashMap();
+            sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+            sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
+            sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+            getBrokerConfiguration().addPortConfiguration(sslPortAttributes);
 
             startBroker();
 
@@ -545,10 +573,11 @@ public class BrokerLoggingTest extends AbstractTestLogging
                 {
                     String log = getLog(rawLog);
 
+                    String id = getBrokerLogId(log);
                     // Ensure we do not have a BRK-1002 message
-                    if (!getMessageID(log).equals(TESTID))
+                    if (!id.equals(TESTID))
                     {
-                        if (getMessageID(log).equals("BRK-1001"))
+                        if (id.equals("BRK-1001"))
                         {
                             foundBRK1001 = true;
                         }
@@ -558,7 +587,7 @@ public class BrokerLoggingTest extends AbstractTestLogging
                     assertTrue("BRK-1001 not logged before this message", foundBRK1001);
 
                     //1
-                    validateMessageID(TESTID, log);
+                    assertEquals("Incorrect message", TESTID, id);
 
                     //2
                     //There will be 4 copies of the startup message (two via SystemOut, and two via Log4J)
@@ -570,16 +599,16 @@ public class BrokerLoggingTest extends AbstractTestLogging
                     //Check the first
                     String message = getMessageString(getLog(listenMessages .get(0)));
                     assertTrue("Expected Listen log not correct" + message,
-                               message.endsWith("Listening on TCP port " + getPort()));
+                               message.endsWith("Listening on [TCP] port " + getPort()));
 
                     // Check the third, ssl listen.
                     message = getMessageString(getLog(listenMessages .get(2)));
                     assertTrue("Expected Listen log not correct" + message,
-                               message.endsWith("Listening on TCP/SSL port " + sslPort));
+                               message.endsWith("Listening on [SSL] port " + DEFAULT_SSL_PORT));
 
                     //4 Test ports open
                     testSocketOpen(getPort());
-                    testSocketOpen(sslPort);
+                    testSocketOpen(DEFAULT_SSL_PORT);
 
                     validation = true;
                 }
@@ -803,11 +832,11 @@ public class BrokerLoggingTest extends AbstractTestLogging
             String TESTID = "BRK-1003";
 
             // Enable SSL on the connection
-            setConfigurationProperty("connector.ssl.enabled", "true");
-            setConfigurationProperty("connector.ssl.keyStorePath", getConfigurationStringProperty("management.ssl.keyStorePath"));
-            setConfigurationProperty("connector.ssl.keyStorePassword", getConfigurationStringProperty("management.ssl.keyStorePassword"));
-
-            Integer sslPort = Integer.parseInt(getConfigurationStringProperty("connector.ssl.port"));
+            Map sslPortAttributes = new HashMap();
+            sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+            sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
+            sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+            getBrokerConfiguration().addPortConfiguration(sslPortAttributes);
 
             startBroker();
 
@@ -848,13 +877,13 @@ public class BrokerLoggingTest extends AbstractTestLogging
                 // Check second, ssl, listen.
                 message = getMessageString(getLog(listenMessages.get(1)));
                 assertTrue("Expected shutdown log not correct" + message,
-                           message.endsWith("TCP/SSL port " + sslPort));
+                           message.endsWith("TCP/SSL port " + DEFAULT_SSL_PORT));
 
                 //4
                 //Test Port closed
                 checkSocketClosed(getPort());
                 //Test SSL Port closed
-                checkSocketClosed(sslPort);
+                checkSocketClosed(DEFAULT_SSL_PORT);
             }
             catch (AssertionFailedError afe)
             {
@@ -999,4 +1028,5 @@ public class BrokerLoggingTest extends AbstractTestLogging
                  + ". Due to:" + e.getMessage());
         }
     }
+
 }
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
index 236202f323..9f532ec5f7 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/SubscriptionLoggingTest.java
@@ -66,8 +66,8 @@ public class SubscriptionLoggingTest extends AbstractTestLogging
 
         _session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
 
-        _queue = (Queue) getInitialContext().lookup(QUEUE);
-        _topic = (Topic) getInitialContext().lookup(TOPIC);
+        _queue = _session.createQueue(getTestQueueName() + "Queue");
+        _topic = _session.createTopic(getTestQueueName() + "Topic");
     }
 
     /**
@@ -434,10 +434,6 @@ public class SubscriptionLoggingTest extends AbstractTestLogging
             throw afe;
         }
         _connection.close();
-
-        //Ensure the queue is drained before the test ends
-        drainQueue(_queue);
-
     }
 
     /**
diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java
index 5f96215269..1ea105ae1a 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/logging/VirtualHostLoggingTest.java
@@ -23,7 +23,6 @@ package org.apache.qpid.server.logging;
 
 import junit.framework.AssertionFailedError;
 
-import org.apache.qpid.server.configuration.ServerConfiguration;
 
 import java.util.Arrays;
 import java.util.List;
@@ -68,7 +67,7 @@ public class VirtualHostLoggingTest extends AbstractTestLogging
         
         try
         {
-            List vhosts = Arrays.asList(getServerConfig().getVirtualHosts());
+            List vhosts = Arrays.asList("test");
 
             assertEquals("Each vhost did not create a store.", vhosts.size(), results.size());
 
@@ -110,23 +109,17 @@ public class VirtualHostLoggingTest extends AbstractTestLogging
 
         // Wait for the correct VHT message to arrive.                                 
         waitForMessage(VHT_PREFIX + "1002");
-        
+
         // Validate each vhost logs a closure
         List results = findMatches(VHT_PREFIX + "1002");
-        
+
         try
         {
-            // Load VirtualHost list from file. 
-            ServerConfiguration configuration = new ServerConfiguration(_configFile);
-            configuration.initialise();
-            List vhosts = Arrays.asList(configuration.getVirtualHosts());
-
-            assertEquals("Each vhost did not close their store.", vhosts.size(), results.size());
+            assertEquals("Each vhost did not close their store.", 1, results.size());
         }
         catch (AssertionFailedError afe)
         {
             dumpLogs(results, _monitor);
-
             throw afe;
         }
     }
diff --git a/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java b/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java
index bcad59a1fa..82b421a531 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/persistent/NoLocalAfterRecoveryTest.java
@@ -39,7 +39,7 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase;
  */
 public class NoLocalAfterRecoveryTest extends QpidBrokerTestCase
 {
-    protected final String MY_TOPIC_SUBSCRIPTION_NAME = this.getName();
+    protected final String MY_TOPIC_SUBSCRIPTION_NAME = getTestQueueName();
     protected static final int SEND_COUNT = 10;
 
     public void testNoLocalNotQueued() throws Exception
diff --git a/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java b/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java
index 8536651ffb..cbf4e032db 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/queue/MultipleTransactedBatchProducerTest.java
@@ -30,6 +30,7 @@ import javax.jms.Message;
 import javax.jms.MessageConsumer;
 import javax.jms.MessageListener;
 import javax.jms.Session;
+
 import java.util.Random;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -54,7 +55,9 @@ public class MultipleTransactedBatchProducerTest extends QpidBrokerTestCase
         //debug level logging often makes this test pass artificially, turn the level down to info.
         setSystemProperty("amqj.server.logging.level", "INFO");
         _receivedLatch = new CountDownLatch(MESSAGE_COUNT * NUM_PRODUCERS);
-        setConfigurationProperty("management.enabled", "true");
+
+        getBrokerConfiguration().addJmxManagementConfiguration();
+
         super.setUp();
         _queueName = getTestQueueName();
         _failMsg = null;
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
index 8ccf74a22b..814936f342 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
@@ -26,6 +26,7 @@ import org.apache.qpid.client.AMQConnection;
 import org.apache.qpid.client.AMQConnectionURL;
 import org.apache.qpid.jms.ConnectionListener;
 import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.test.utils.QpidBrokerTestCase;
 import org.apache.qpid.url.URLSyntaxException;
 
@@ -45,7 +46,7 @@ import java.util.concurrent.TimeUnit;
 /**
  * Abstract test case for ACLs.
  * 
- * This base class contains convenience methods to mange ACL files and implements a mechanism that allows each
+ * This base class contains convenience methods to manage ACL files and implements a mechanism that allows each
  * test method to run its own setup code before the broker starts.
  * 
  * TODO move the pre broker-startup setup method invocation code to {@link QpidBrokerTestCase}
@@ -58,25 +59,11 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
 {
     /** Used to synchronise {@link #tearDown()} when exceptions are thrown */
     protected CountDownLatch _exceptionReceived;
-    
-    /** Override this to return the name of the configuration XML file. */
-    public String getConfig()
-    {
-        return "config-systests.xml";
-    }
 
-    /**
-     * This setup method checks {@link #getConfig()} and {@link #getHostList()} to initialise the broker with specific
-     * ACL configurations and then runs an optional per-test setup method, which is simply a method with the same name
-     * as the test, but starting with {@code setUp} rather than {@code test}.
-     * 
-     * @see org.apache.qpid.test.utils.QpidBrokerTestCase#setUp()
-     */
     @Override
     public void setUp() throws Exception
     {
-        // Initialise ACLs.
-        _configFile = new File("build" + File.separator + "etc" + File.separator + getConfig());
+        getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, System.getProperty(QPID_HOME) + "/etc/groups-systests");
 
         // run test specific setup
         String testSetup = StringUtils.replace(getName(), "test", "setUp");
@@ -123,11 +110,11 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
 
         if (vhost == null)
         {
-            testcase.setConfigurationProperty("security.acl", aclFile.getAbsolutePath());
+            testcase.getBrokerConfiguration().setBrokerAttribute(Broker.ACL_FILE, aclFile.getAbsolutePath());
         }
         else
         {
-            testcase.setConfigurationProperty("virtualhosts.virtualhost." + vhost + ".security.acl", aclFile.getAbsolutePath());
+            testcase.setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + vhost + ".security.acl", aclFile.getAbsolutePath());
         }
 
         PrintWriter out = new PrintWriter(new FileWriter(aclFile));
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
index ceff2b998a..1830040007 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
@@ -33,14 +33,19 @@ import java.lang.management.RuntimeMXBean;
  */
 public class ExternalACLJMXTest extends AbstractACLTestCase
 {
+
     private JMXTestUtils _jmx;
 
     private static final String TEST_QUEUE_OWNER = "admin";
     private static final String TEST_VHOST = "test";
+    private static final String TEST2_VHOST = "test2";
 
     @Override
     public void setUp() throws Exception
     {
+        createTestVirtualHost(0, TEST_VHOST);
+        createTestVirtualHost(0, TEST2_VHOST);
+
         _jmx = new JMXTestUtils(this);
         _jmx.setUp();
         super.setUp();
@@ -54,15 +59,14 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
         super.tearDown();
     }
 
-    /**
-     * Ensure an empty ACL defaults to DENY ALL.
-     */
-    public void setUpDenyAllIsDefault() throws Exception
+    public void setUpDenyAllIsCatchAllRule() throws Exception
     {
-        writeACLFile(null, "#Empty ACL file");
+        writeACLFile(null,
+                "ACL ALLOW admin ACCESS MANAGEMENT",
+                "#No more rules, default catch all (deny all) should apply");
     }
 
-    public void testDenyAllIsDefault() throws Exception
+    public void testDenyAllIsCatchAllRule() throws Exception
     {
         //try a broker-level method
         ServerInformation info = _jmx.getServerInformation();
@@ -115,6 +119,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
     public void setUpVhostAllowOverridesGlobalDeny() throws Exception
     {
         writeACLFile(null,
+                "ACL ALLOW admin ACCESS MANAGEMENT",
                 "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
         writeACLFile(TEST_VHOST,
                 "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
@@ -128,7 +133,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
         //try a vhost-level method on a different vhost
         try
         {
-            _jmx.createQueue("development", getTestQueueName(), TEST_QUEUE_OWNER, true);
+            _jmx.createQueue(TEST2_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true);
             fail("Exception not thrown");
         }
         catch (SecurityException e)
@@ -144,6 +149,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
     public void setUpUpdateComponentOnlyAllow() throws Exception
     {
         writeACLFile(null,
+                "ACL ALLOW admin ACCESS MANAGEMENT",
                 "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager'");
     }
 
@@ -162,6 +168,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
     public void setUpUpdateMethodOnlyAllow() throws Exception
     {
         writeACLFile(null,
+                "ACL ALLOW admin ACCESS MANAGEMENT",
                 "ACL ALLOW admin UPDATE METHOD");
     }
 
@@ -179,8 +186,8 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
      */
     public void setUpCreateQueueSuccess() throws Exception
     {
-        writeACLFile(TEST_VHOST,
-                "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
+        writeACLFile(null, "ACL ALLOW admin ACCESS MANAGEMENT");
+        writeACLFile(TEST_VHOST, "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
     }
 
     public void testCreateQueueSuccess() throws Exception
@@ -194,6 +201,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
      */
     public void setUpCreateQueueSuccessNoAMQPRights() throws Exception
     {
+        writeACLFile(null, "ACL ALLOW admin ACCESS MANAGEMENT");
         writeACLFile(TEST_VHOST,
                 "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'",
                 "ACL DENY admin CREATE QUEUE");
@@ -210,6 +218,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
      */
     public void setUpCreateQueueDenied() throws Exception
     {
+        writeACLFile(null, "ACL ALLOW admin ACCESS MANAGEMENT");
         writeACLFile(TEST_VHOST,
                 "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
     }
@@ -234,6 +243,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
     public void setUpServerInformationUpdateDenied() throws Exception
     {
         writeACLFile(null,
+                "ACL ALLOW admin ACCESS MANAGEMENT",
                 "ACL DENY admin UPDATE METHOD component='ServerInformation' name='resetStatistics'");
     }
 
@@ -258,6 +268,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
     public void setUpServerInformationAccessGranted() throws Exception
     {
         writeACLFile(null,
+        "ACL ALLOW admin ACCESS MANAGEMENT",
         "ACL ALLOW-LOG admin ACCESS METHOD component='ServerInformation' name='getManagementApiMajorVersion'");
     }
 
@@ -284,6 +295,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
     public void setUpServerInformationUpdateMethodPermission() throws Exception
     {
         writeACLFile(null,
+                "ACL ALLOW admin ACCESS MANAGEMENT",
                 "ACL ALLOW admin UPDATE METHOD component='ServerInformation' name='resetStatistics'");
     }
 
@@ -300,7 +312,9 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
      */
     public void setUpServerInformationAllMethodPermissions() throws Exception
     {
-        writeACLFile(null, "ACL ALLOW admin ALL METHOD component='ServerInformation'");
+        writeACLFile(null,
+                "ACL ALLOW admin ACCESS MANAGEMENT",
+                "ACL ALLOW admin ALL METHOD component='ServerInformation'");
     }
 
     public void testServerInformationAllMethodPermissions() throws Exception
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java
index 0e45ca9493..8324ac74a5 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java
@@ -319,8 +319,12 @@ public class ExternalACLTest extends AbstractACLTestCase
 
     public void setUpRequestResponseSuccess() throws Exception
     {
-        writeACLFile("test", "GROUP messaging-users client server",
-                             "ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST",
+        // The group "messaging-users", referenced in the ACL below, is currently defined
+        // in broker/etc/groups-systests.
+        // We tolerate a dependency from this test to that file because its
+        // contents are expected to change rarely.
+
+        writeACLFile("test", "ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST",
                              "# Server side",
                              "ACL ALLOW-LOG server CREATE QUEUE name=\"example.RequestQueue\"" ,
                              "ACL ALLOW-LOG server BIND EXCHANGE",
@@ -389,14 +393,44 @@ public class ExternalACLTest extends AbstractACLTestCase
         conn.start();
 
         // create kipper
-        Topic kipper = sess.createTopic("kipper");
-        TopicSubscriber subscriber = sess.createDurableSubscriber(kipper, "kipper");
+        String topicName = "kipper";
+        Topic topic = sess.createTopic(topicName);
+        TopicSubscriber subscriber = sess.createDurableSubscriber(topic, topicName);
 
         subscriber.close();
-        sess.unsubscribe("kipper");
+        sess.unsubscribe(topicName);
 
         //Do something to show connection is active.
         sess.rollback();
         conn.close();
     }
+
+    public void setUpFirewallAllow() throws Exception
+    {
+        writeACLFile("test", "ACL ALLOW client ACCESS VIRTUALHOST from_network=\"127.0.0.1\"");
+    }
+
+    public void testFirewallAllow() throws Exception
+    {
+        getConnection("test", "client", "guest");
+        // test pass because we successfully connected
+    }
+
+    public void setUpFirewallDeny() throws Exception
+    {
+        writeACLFile("test", "ACL DENY client ACCESS VIRTUALHOST from_network=\"127.0.0.1\"");
+    }
+
+    public void testFirewallDeny() throws Exception
+    {
+        try
+        {
+            getConnection("test", "client", "guest");
+            fail("We expected the connection to fail");
+        }
+        catch(JMSException e)
+        {
+            // pass
+        }
+    }
 }
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java
new file mode 100644
index 0000000000..c7a43a292b
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationTest.java
@@ -0,0 +1,184 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ *
+ */
+package org.apache.qpid.server.security.auth.manager;
+
+import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE;
+import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD;
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE;
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+
+public class ExternalAuthenticationTest extends QpidBrokerTestCase
+{
+    @Override
+    protected void setUp() throws Exception
+    {
+        // not calling super.setUp() to avoid broker start-up
+    }
+
+    /**
+     * Tests that when EXTERNAL authentication is used on the SSL port, clients presenting certificates are able to connect.
+     * Also, checks that default authentication manager PrincipalDatabaseAuthenticationManager is used on non SSL port.
+     */
+    public void testExternalAuthenticationManagerOnSSLPort() throws Exception
+    {
+        setCommonBrokerSSLProperties(true);
+        getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_SSL_PORT, Port.AUTHENTICATION_MANAGER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
+        super.setUp();
+
+        setClientKeystoreProperties();
+        setClientTrustoreProperties();
+
+        try
+        {
+            getExternalSSLConnection(false);
+        }
+        catch (JMSException e)
+        {
+            fail("Should be able to create a connection to the SSL port: " + e.getMessage());
+        }
+
+        try
+        {
+            getConnection();
+        }
+        catch (JMSException e)
+        {
+            fail("Should be able to create a connection with credentials to the standard port: " + e.getMessage());
+        }
+
+    }
+
+    /**
+     * Tests that when EXTERNAL authentication manager is set as the default, clients presenting certificates are able to connect.
+     * Also, checks a client with valid username and password but not using ssl is unable to connect to the non SSL port.
+     */
+    public void testExternalAuthenticationManagerAsDefault() throws Exception
+    {
+        setCommonBrokerSSLProperties(true);
+        getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
+        super.setUp();
+
+        setClientKeystoreProperties();
+        setClientTrustoreProperties();
+
+        try
+        {
+            getConnection();
+            fail("Connection should not succeed");
+        }
+        catch (JMSException e)
+        {
+            // pass
+        }
+
+        try
+        {
+            getExternalSSLConnection(false);
+        }
+        catch (JMSException e)
+        {
+            fail("Should be able to create a connection to the SSL port. " + e.getMessage());
+        }
+    }
+
+    /**
+     * Tests that when EXTERNAL authentication manager is set as the default, clients without certificates are unable to connect to the SSL port
+     * even with valid username and password.
+     */
+    public void testExternalAuthenticationManagerWithoutClientKeyStore() throws Exception
+    {
+        setCommonBrokerSSLProperties(false);
+        getBrokerConfiguration().setBrokerAttribute(Broker.DEFAULT_AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
+        super.setUp();
+
+        setClientTrustoreProperties();
+
+        try
+        {
+            getExternalSSLConnection(true);
+            fail("Connection should not succeed");
+        }
+        catch (JMSException e)
+        {
+            // pass
+        }
+    }
+
+    private Connection getExternalSSLConnection(boolean includeUserNameAndPassword) throws Exception
+    {
+        String url = "amqp://%s@test/?brokerlist='tcp://localhost:%s?ssl='true'&sasl_mechs='EXTERNAL''";
+        if (includeUserNameAndPassword)
+        {
+            url = String.format(url, "guest:guest", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT));
+        }
+        else
+        {
+            url = String.format(url, ":", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT));
+        }
+        return getConnection(new AMQConnectionURL(url));
+    }
+
+    private void setCommonBrokerSSLProperties(boolean needClientAuth) throws ConfigurationException
+    {
+        TestBrokerConfiguration config = getBrokerConfiguration();
+        Map sslPortAttributes = new HashMap();
+        sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+        sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
+        sslPortAttributes.put(Port.NEED_CLIENT_AUTH, String.valueOf(needClientAuth));
+        sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+        config.addPortConfiguration(sslPortAttributes);
+
+        Map externalAuthProviderAttributes = new HashMap();
+        externalAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, ExternalAuthenticationManagerFactory.PROVIDER_TYPE);
+        externalAuthProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_EXTERNAL_PROVIDER);
+        config.addAuthenticationProviderConfiguration(externalAuthProviderAttributes);
+    }
+
+    private void setClientKeystoreProperties()
+    {
+        setSystemProperty("javax.net.ssl.keyStore", KEYSTORE);
+        setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD);
+    }
+
+    private void setClientTrustoreProperties()
+    {
+        setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
+        setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
+        setSystemProperty("javax.net.debug", "ssl");
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java
index 858b32c24c..f41f1159ab 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/security/auth/manager/MultipleAuthenticationManagersTest.java
@@ -20,28 +20,44 @@
  */
 package org.apache.qpid.server.security.auth.manager;
 
+import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE;
+import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD;
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE;
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 import javax.jms.Connection;
 import javax.jms.JMSException;
 import org.apache.qpid.AMQException;
 import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
 import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
 
 public class MultipleAuthenticationManagersTest extends QpidBrokerTestCase
 {
-    private static final String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks";
-    private static final String KEYSTORE_PASSWORD = "password";
-    private static final String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks";
-    private static final String TRUSTSTORE_PASSWORD = "password";
-
     @Override
     protected void setUp() throws Exception
     {
-        setConfigurationProperty("connector.ssl.enabled", "true");
-        setConfigurationProperty("connector.ssl.sslOnly", "false");
-        setConfigurationProperty("security.anonymous-auth-manager", "");
-        setConfigurationProperty("security.default-auth-manager", "PrincipalDatabaseAuthenticationManager");
-        setConfigurationProperty("security.port-mappings.port-mapping.port", String.valueOf(QpidBrokerTestCase.DEFAULT_SSL_PORT));
-        setConfigurationProperty("security.port-mappings.port-mapping.auth-manager", "AnonymousAuthenticationManager");
+        TestBrokerConfiguration config = getBrokerConfiguration();
+
+        Map externalAuthProviderAttributes = new HashMap();
+        externalAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, AnonymousAuthenticationManagerFactory.PROVIDER_TYPE);
+        externalAuthProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER);
+        config.addAuthenticationProviderConfiguration(externalAuthProviderAttributes);
+
+        Map sslPortAttributes = new HashMap();
+        sslPortAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+        sslPortAttributes.put(Port.PORT, DEFAULT_SSL_PORT);
+        sslPortAttributes.put(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_SSL_PORT);
+        sslPortAttributes.put(Port.AUTHENTICATION_MANAGER, TestBrokerConfiguration.ENTRY_NAME_ANONYMOUS_PROVIDER);
+        config.addPortConfiguration(sslPortAttributes);
 
         // set the ssl system properties
         setSystemProperty("javax.net.ssl.keyStore", KEYSTORE);
diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java
deleted file mode 100644
index f5adf815aa..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/server/security/firewall/FirewallConfigTest.java
+++ /dev/null
@@ -1,283 +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.firewall;
-
-import org.apache.qpid.client.AMQConnectionURL;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-import javax.jms.Connection;
-import javax.jms.JMSException;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-public class FirewallConfigTest extends QpidBrokerTestCase 
-{
-    private File _tmpConfig, _tmpVirtualhosts;
-    private String _ipAddressOfBrokerHost;
-
-    @Override
-    protected void setUp() throws Exception
-    {
-        // Setup initial config file.
-        _configFile = new File("build/etc/config-systests-firewall.xml");
-        
-        // Setup temporary config file
-        _tmpConfig = File.createTempFile("config-systests-firewall", ".xml");
-        setSystemProperty("QPID_FIREWALL_CONFIG_SETTINGS", _tmpConfig.getAbsolutePath());
-        _tmpConfig.deleteOnExit();
-
-        // Setup temporary virtualhosts file
-        _tmpVirtualhosts = File.createTempFile("virtualhosts-systests-firewall", ".xml");
-        setSystemProperty("QPID_FIREWALL_VIRTUALHOSTS_SETTINGS", _tmpVirtualhosts.getAbsolutePath());
-        _tmpVirtualhosts.deleteOnExit();
-
-        _ipAddressOfBrokerHost = getIpAddressOfBrokerHost();
-    }
-
-    private void writeFirewallFile(boolean allow, boolean inVhost) throws IOException
-    {
-        FileWriter out = new FileWriter(inVhost ? _tmpVirtualhosts : _tmpConfig);
-        if (inVhost) 
-        {
-            out.write("");
-        }
-        else
-        {
-            out.write("");
-        }
-        out.write("");
-        out.write("");
-        out.write("");
-        if (inVhost)
-        {
-            out.write("");
-        }
-        else
-        {
-            out.write("");
-        }
-        out.close();
-    }
-
-    public void testVhostAllowBrokerDeny() throws Exception
-    {
-
-        _configFile = new File("build/etc/config-systests-firewall-2.xml");
-        
-        super.setUp();
-        try 
-        {
-            //Try to get a connection to the 'test2' vhost
-            //This is expected to succeed as it is allowed at the vhost level
-            getConnection(new AMQConnectionURL("amqp://guest:guest@clientid/test2?brokerlist='" + getBroker() + "'"));
-        } 
-        catch (JMSException e)
-        {
-            e.getLinkedException().printStackTrace();
-            fail("The connection was expected to succeed: " + e.getMessage());
-        }
-
-        try 
-        {
-            //Try to get a connection to the 'test' vhost
-            //This is expected to fail as it is denied at the broker level
-            getConnection();
-            fail("We expected the connection to fail");
-        } 
-        catch (JMSException e)
-        {
-            //ignore
-        }
-    }
-    
-    public void testVhostDenyBrokerAllow() throws Exception
-    {
-        _configFile = new File("build/etc/config-systests-firewall-3.xml");
-        
-        super.setUp();
-        try 
-        {
-            //Try to get a connection to the 'test2' vhost
-            //This is expected to fail as it is denied at the vhost level
-            getConnection(new AMQConnectionURL("amqp://guest:guest@clientid/test2?brokerlist='" + getBroker() + "'"));
-            fail("The connection was expected to fail");
-        } 
-        catch (JMSException e)
-        {
-            //ignore
-        }
-
-        try 
-        {
-            //Try to get a connection to the 'test' vhost
-            //This is expected to succeed as it is allowed at the broker level
-            getConnection();
-        } 
-        catch (JMSException e)
-        {
-            e.getLinkedException().printStackTrace();
-            fail("The connection was expected to succeed: " + e.getMessage());
-        }
-    }
- 
-    public void testDenyOnRestart() throws Exception
-    {
-        testDeny(false, new Runnable() {
-
-            public void run()
-            {
-                try
-                {
-                    restartBroker();
-                } catch (Exception e)
-                {
-                    fail(e.getMessage());
-                }
-            }
-        });
-    }
-    
-    public void testDenyOnRestartInVhost() throws Exception
-    {
-        testDeny(true, new Runnable() {
-
-            public void run()
-            {
-                try
-                {
-                    restartBroker();
-                } catch (Exception e)
-                {
-                    fail(e.getMessage());
-                }
-            }
-        });
-    }
-    
-    public void testAllowOnReloadInVhost() throws Exception
-    {
-        testFirewall(false, true, new Runnable() {
-
-            public void run()
-            {
-                try
-                {
-                    reloadBrokerSecurityConfig();
-                } catch (Exception e)
-                {
-                    fail(e.getMessage());
-                }
-            }
-        });
-    }
-    
-    public void testDenyOnReload() throws Exception
-    {
-        testDeny(false, new Runnable() {
-
-            public void run()
-            {
-                try
-                {
-                    reloadBrokerSecurityConfig();
-                } catch (Exception e)
-                {
-                    fail(e.getMessage());
-                }
-            }
-        }
-        );
-    }
-
-    public void testDenyOnReloadInVhost() throws Exception
-    {
-        testDeny(true, new Runnable() {
-
-            public void run()
-            {
-                try
-                {
-                    reloadBrokerSecurityConfig();
-                } catch (Exception e)
-                {
-                   fail(e.getMessage());
-                }
-            }
-        }
-        );
-       
-    }
-
-    private void testDeny(boolean inVhost, Runnable restartOrReload) throws Exception
-    {
-        testFirewall(true, inVhost, restartOrReload);
-    }
-
-    /*
-     * Check we can get a connection
-     */
-    private boolean checkConnection() throws Exception
-    {
-        Exception exception  = null;
-        Connection conn = null;
-        try 
-        {
-            conn = getConnection();
-        } 
-        catch (JMSException e)
-        {
-            exception = e;
-        }
-        
-        return conn != null;
-    }
-
-    private void testFirewall(boolean initial, boolean inVhost, Runnable restartOrReload) throws Exception
-    {
-        
-        writeFirewallFile(initial, inVhost);
-        setConfigurationProperty("management.enabled", String.valueOf(true));
-        super.setUp();
-
-        assertEquals("Initial connection check failed", initial, checkConnection());
-
-        // Reload changed firewall file after restart or reload
-        writeFirewallFile(!initial, inVhost);
-        restartOrReload.run();
-        
-        assertEquals("Second connection check failed", !initial, checkConnection());
-    }
-
-    private String getIpAddressOfBrokerHost()
-    {
-        String brokerHost = getBroker().getHost();
-        try
-        {
-            return InetAddress.getByName(brokerHost).getHostAddress();
-        }
-        catch (UnknownHostException e)
-        {
-            throw new RuntimeException("Could not determine IP address of host : " + brokerHost, e);
-        }
-
-    }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java b/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java
index c38fcd9199..6d53896371 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java
@@ -27,10 +27,13 @@ import org.apache.qpid.client.AMQQueue;
 import org.apache.qpid.client.AMQSession;
 import org.apache.qpid.exchange.ExchangeDefaults;
 import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.server.model.Broker;
 import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
 import org.apache.qpid.util.LogMonitor;
 
 import java.util.List;
+import java.util.Map;
 
 import javax.jms.Connection;
 import javax.jms.Destination;
@@ -45,46 +48,55 @@ import javax.jms.TextMessage;
  */
 public class StatisticsReportingTest extends QpidBrokerTestCase
 {
+    private static final String VHOST_NAME1 = "vhost1";
+    private static final String VHOST_NAME2 = "vhost2";
+    private static final String VHOST_NAME3 = "vhost3";
+    private static long STATISTICS_REPORTING_PERIOD_IN_SECONDS = 10l;
+
     protected LogMonitor _monitor;
     protected static final String USER = "admin";
 
-    protected Connection _test, _dev, _local;
+    protected Connection _conToVhost1, _conToVhost2, _conToVhost3;
     protected String _queueName = "statistics";
     protected Destination _queue;
     protected String _brokerUrl;
+    private long _startTestTime;
 
     @Override
     public void setUp() throws Exception
     {
-        setConfigurationProperty("statistics.generation.broker", "true");
-        setConfigurationProperty("statistics.generation.virtualhosts", "true");
+        createTestVirtualHost(0, VHOST_NAME1);
+        createTestVirtualHost(0, VHOST_NAME2);
+        createTestVirtualHost(0, VHOST_NAME3);
 
         if (getName().equals("testEnabledStatisticsReporting"))
         {
-            setConfigurationProperty("statistics.reporting.period", "10");
+            TestBrokerConfiguration config = getBrokerConfiguration();
+            config.removeObjectConfiguration(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST);
+            config.setBrokerAttribute(Broker.STATISTICS_REPORTING_PERIOD, STATISTICS_REPORTING_PERIOD_IN_SECONDS);
         }
 
         _monitor = new LogMonitor(_outputFile);
+        _startTestTime = System.currentTimeMillis();
 
         super.setUp();
 
         _brokerUrl = getBroker().toString();
-        _test = new AMQConnection(_brokerUrl, USER, USER, "clientid", "test");
-        _dev = new AMQConnection(_brokerUrl, USER, USER, "clientid", "development");
-        _local = new AMQConnection(_brokerUrl, USER, USER, "clientid", "localhost");
-
-        _test.start();
-        _dev.start();
-        _local.start();
+        _conToVhost1 = new AMQConnection(_brokerUrl, USER, USER, "clientid", VHOST_NAME1);
+        _conToVhost2 = new AMQConnection(_brokerUrl, USER, USER, "clientid", VHOST_NAME2);
+        _conToVhost3 = new AMQConnection(_brokerUrl, USER, USER, "clientid", VHOST_NAME3);
 
+        _conToVhost1.start();
+        _conToVhost2.start();
+        _conToVhost3.start();
     }
 
     @Override
     public void tearDown() throws Exception
     {
-        _test.close();
-        _dev.close();
-        _local.close();
+        _conToVhost1.close();
+        _conToVhost2.close();
+        _conToVhost3.close();
 
         super.tearDown();
     }
@@ -94,21 +106,30 @@ public class StatisticsReportingTest extends QpidBrokerTestCase
      */
     public void testEnabledStatisticsReporting() throws Exception
     {
-        sendUsing(_test, 10, 100);
-        sendUsing(_dev, 20, 100);
-        sendUsing(_local, 15, 100);
-
-        Thread.sleep(10 * 1000); // 15s
-
-        List brokerStatsData = _monitor.findMatches("BRK-1008");
-        List brokerStatsMessages = _monitor.findMatches("BRK-1009");
-        List vhostStatsData = _monitor.findMatches("VHT-1003");
-        List vhostStatsMessages = _monitor.findMatches("VHT-1004");
-
-        assertEquals("Incorrect number of broker data stats log messages", 2, brokerStatsData.size());
-        assertEquals("Incorrect number of broker message stats log messages", 2, brokerStatsMessages.size());
-        assertEquals("Incorrect number of virtualhost data stats log messages", 6, vhostStatsData.size());
-        assertEquals("Incorrect number of virtualhost message stats log messages", 6, vhostStatsMessages.size());
+        sendUsing(_conToVhost1, 10, 100);
+        sendUsing(_conToVhost2, 20, 100);
+        sendUsing(_conToVhost3, 15, 100);
+
+        Thread.sleep(STATISTICS_REPORTING_PERIOD_IN_SECONDS * 1000);
+
+        Map> brokerStatsData = _monitor.findMatches("BRK-1008", "BRK-1009", "VHT-1003", "VHT-1004");
+        long endTestTime = System.currentTimeMillis();
+
+        int maxNumberOfReports = (int)((endTestTime - _startTestTime)/STATISTICS_REPORTING_PERIOD_IN_SECONDS);
+
+        int brk1008LinesNumber = brokerStatsData.get("BRK-1008").size();
+        int brk1009LinesNumber = brokerStatsData.get("BRK-1009").size();
+        int vht1003LinesNumber = brokerStatsData.get("VHT-1003").size();
+        int vht1004LinesNumber = brokerStatsData.get("VHT-1004").size();
+
+        assertTrue("Incorrect number of broker data stats log messages:" + brk1008LinesNumber, 2 <= brk1008LinesNumber
+                && brk1008LinesNumber <= maxNumberOfReports * 2);
+        assertTrue("Incorrect number of broker message stats log messages:" + brk1009LinesNumber, 2 <= brk1009LinesNumber
+                && brk1009LinesNumber <= maxNumberOfReports * 2);
+        assertTrue("Incorrect number of virtualhost data stats log messages:" + vht1003LinesNumber, 6 <= vht1003LinesNumber
+                && vht1003LinesNumber <= maxNumberOfReports * 6);
+        assertTrue("Incorrect number of virtualhost message stats log messages: " + vht1004LinesNumber, 6 <= vht1004LinesNumber
+                && vht1004LinesNumber <= maxNumberOfReports * 6);
     }
 
     /**
@@ -116,9 +137,9 @@ public class StatisticsReportingTest extends QpidBrokerTestCase
      */
     public void testNotEnabledStatisticsReporting() throws Exception
     {
-        sendUsing(_test, 10, 100);
-        sendUsing(_dev, 20, 100);
-        sendUsing(_local, 15, 100);
+        sendUsing(_conToVhost1, 10, 100);
+        sendUsing(_conToVhost2, 20, 100);
+        sendUsing(_conToVhost3, 15, 100);
 
         Thread.sleep(10 * 1000); // 15s
 
@@ -135,7 +156,7 @@ public class StatisticsReportingTest extends QpidBrokerTestCase
 
     private void sendUsing(Connection con, int number, int size) throws Exception
     {
-        Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
+        Session session = con.createSession(true, Session.SESSION_TRANSACTED);
         createQueue(session);
         MessageProducer producer = session.createProducer(_queue);
         String content = new String(new byte[size]);
@@ -144,6 +165,8 @@ public class StatisticsReportingTest extends QpidBrokerTestCase
         {
             producer.send(msg);
         }
+        session.commit();
+        session.close();
     }
 
     private void createQueue(Session session) throws AMQException, JMSException
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
index 9db04b64b3..6d38004451 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
@@ -27,8 +27,6 @@ import org.apache.qpid.AMQStoreException;
 import org.apache.qpid.framing.FieldTable;
 import org.apache.qpid.server.binding.Binding;
 import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.federation.Bridge;
-import org.apache.qpid.server.federation.BrokerLink;
 import org.apache.qpid.server.message.EnqueableMessage;
 import org.apache.qpid.server.message.ServerMessage;
 import org.apache.qpid.server.queue.AMQQueue;
@@ -322,35 +320,6 @@ public class SlowMessageStore implements MessageStore
         doPostDelay("updateQueue");
     }
 
-
-    public void createBrokerLink(final BrokerLink link) throws AMQStoreException
-    {
-        doPreDelay("createBrokerLink");
-        _durableConfigurationStore.createBrokerLink(link);
-        doPostDelay("createBrokerLink");
-    }
-
-    public void deleteBrokerLink(final BrokerLink link) throws AMQStoreException
-    {
-        doPreDelay("deleteBrokerLink");
-        _durableConfigurationStore.deleteBrokerLink(link);
-        doPostDelay("deleteBrokerLink");
-    }
-
-    public void createBridge(final Bridge bridge) throws AMQStoreException
-    {
-        doPreDelay("createBridge");
-        _durableConfigurationStore.createBridge(bridge);
-        doPostDelay("createBridge");
-    }
-
-    public void deleteBridge(final Bridge bridge) throws AMQStoreException
-    {
-        doPreDelay("deleteBridge");
-        _durableConfigurationStore.deleteBridge(bridge);
-        doPostDelay("deleteBridge");
-    }
-
     @Override
     public void activate() throws Exception
     {
diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java b/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java
index 9fb1db3a4f..61ca6d9c28 100644
--- a/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java
@@ -60,9 +60,9 @@ public class StoreOverfullTest extends QpidBrokerTestCase
 
     public void setUp() throws Exception
     {
-        setConfigurationProperty("virtualhosts.virtualhost.test.store.class", QuotaMessageStore.class.getName());
-        setConfigurationProperty("virtualhosts.virtualhost.test.store.overfull-size", String.valueOf(OVERFULL_SIZE));
-        setConfigurationProperty("virtualhosts.virtualhost.test.store.underfull-size", String.valueOf(UNDERFULL_SIZE));
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.store.class", QuotaMessageStore.class.getName());
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.store.overfull-size", String.valueOf(OVERFULL_SIZE));
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.store.underfull-size", String.valueOf(UNDERFULL_SIZE));
 
         super.setUp();
 
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/GlobalQueuesTest.java b/java/systests/src/main/java/org/apache/qpid/systest/GlobalQueuesTest.java
deleted file mode 100644
index 9ff143daf3..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/systest/GlobalQueuesTest.java
+++ /dev/null
@@ -1,223 +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.systest;
-
-import org.apache.commons.configuration.ConfigurationException;
-
-import javax.jms.Session;
-import javax.naming.NamingException;
-import java.io.IOException;
-
-/**
- * QPID-1447 : Add slow consumer detection and disconnection.
- *
- * Slow consumers should on a topic should expect to receive a
- * 506 : Resource Error if the hit a predefined threshold.
- */
-public class GlobalQueuesTest extends TestingBaseCase
-{
-
-    protected String CONFIG_SECTION = ".queues";
-
-    /**
-     *  Queue Configuration
-
-     
-     
-     4235264
-
-     
-     600000
-
-     
-     50
-
-     
-     
-     TopicDelete
-     
-     
-     
-     
-     
-
-     */
-
-
-    /**
-     *  VirtualHost Plugin Configuration
-
-     
-     1
-     MINUTES
-     
-
-     */
-
-    public void setConfig(String property, String value, boolean deleteDurable) throws NamingException, IOException, ConfigurationException
-    {
-        setProperty(CONFIG_SECTION + ".slow-consumer-detection." +
-                    "policy.name", "TopicDelete");
-
-        setProperty(CONFIG_SECTION + ".slow-consumer-detection." +
-                    property, value);
-
-        if (deleteDurable)
-        {
-            setProperty(CONFIG_SECTION + ".slow-consumer-detection." +
-                        "policy.topicdelete.delete-persistent", "");
-        }
-    }
-
-    /**
-     * Test that setting messageCount takes affect on topics
-     *
-     * We send 10 messages and disconnect at 9
-     *
-     * @throws Exception
-     */
-    public void testTopicConsumerMessageCount() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        setConfig("messageCount", String.valueOf(MAX_QUEUE_MESSAGE_COUNT - 1), false);
-
-        //Start the broker
-        startBroker();
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, false);
-    }
-
-    /**
-     * Test that setting depth has an effect on topics
-     *
-     * Sets the message size for the test
-     * Sets the depth to be 9 * the depth
-     * Ensure that sending 10 messages causes the disconnection
-     *
-     * @throws Exception
-     */
-    public void testTopicConsumerMessageSize() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        setConfig("depth", String.valueOf(MESSAGE_SIZE * 9), false);
-
-        //Start the broker
-        startBroker();
-
-        setMessageSize(MESSAGE_SIZE);
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, false);
-    }
-
-    /**
-     * Test that setting messageAge has an effect on topics
-     *
-     * Sets the messageAge to be half the disconnection wait timeout
-     * Send 10 messages and then ensure that we get disconnected as we will
-     * wait for the full timeout.
-     *
-     * @throws Exception
-     */
-    public void testTopicConsumerMessageAge() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        setConfig("messageAge", String.valueOf(DISCONNECTION_WAIT / 2), false);
-
-        //Start the broker
-        startBroker();
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, false);
-    }
-
-    /**
-     * Test that setting messageCount takes affect on a durable Consumer
-     *
-     * Ensure we set the delete-persistent option
-     *
-     * We send 10 messages and disconnect at 9
-     *
-     * @throws Exception
-     */
-
-    public void testTopicDurableConsumerMessageCount() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        setConfig("messageCount", String.valueOf(MAX_QUEUE_MESSAGE_COUNT - 1), true);
-
-        //Start the broker
-        startBroker();
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, true);
-    }
-
-    /**
-     * Test that setting depth has an effect on durable consumer topics
-     *
-     * Ensure we set the delete-persistent option
-     *
-     * Sets the message size for the test
-     * Sets the depth to be 9 * the depth
-     * Ensure that sending 10 messages causes the disconnection
-     *
-     * @throws Exception
-     */
-    public void testTopicDurableConsumerMessageSize() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        setConfig("depth", String.valueOf(MESSAGE_SIZE * 9), true);
-
-        //Start the broker
-        startBroker();
-
-        setMessageSize(MESSAGE_SIZE);
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, true);
-    }
-
-    /**
-     * Test that setting messageAge has an effect on topics
-     *
-     * Ensure we set the delete-persistent option
-     *
-     * Sets the messageAge to be 1/5 the disconnection wait timeout (or 1sec)
-     * Send 10 messages and then ensure that we get disconnected as we will
-     * wait for the full timeout.
-     *
-     * @throws Exception
-     */
-    public void testTopicDurableConsumerMessageAge() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        setConfig("messageAge", String.valueOf(DISCONNECTION_WAIT / 5), true);
-
-        //Start the broker
-        startBroker();
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, true);
-    }
-
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/GlobalTopicsTest.java b/java/systests/src/main/java/org/apache/qpid/systest/GlobalTopicsTest.java
deleted file mode 100644
index 6297478883..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/systest/GlobalTopicsTest.java
+++ /dev/null
@@ -1,31 +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.systest;
-
-public class GlobalTopicsTest extends GlobalQueuesTest
-{
-    @Override
-    public void setUp() throws Exception
-    {
-        CONFIG_SECTION = ".topics";
-        super.setUp();
-    }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/MergeConfigurationTest.java b/java/systests/src/main/java/org/apache/qpid/systest/MergeConfigurationTest.java
deleted file mode 100644
index 993d71ea34..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/systest/MergeConfigurationTest.java
+++ /dev/null
@@ -1,109 +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.systest;
-
-import org.apache.commons.configuration.ConfigurationException;
-
-import javax.jms.Session;
-import javax.naming.NamingException;
-import java.io.IOException;
-
-public class MergeConfigurationTest extends TestingBaseCase
-{
-
-    protected int topicCount = 0;
-
-
-    public void configureTopic(String topic, int msgCount) throws NamingException, IOException, ConfigurationException
-    {
-
-        setProperty(".topics.topic("+topicCount+").name", topic);
-        setProperty(".topics.topic("+topicCount+").slow-consumer-detection.messageCount", String.valueOf(msgCount));
-        setProperty(".topics.topic("+topicCount+").slow-consumer-detection.policy.name", "TopicDelete");
-        topicCount++;
-    }
-
-
-    /**
-     * Test that setting messageCount takes affect on topics
-     *
-     * We send 10 messages and disconnect at 9
-     *
-     * @throws Exception
-     */
-    public void testTopicConsumerMessageCount() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        configureTopic(getName(), (MAX_QUEUE_MESSAGE_COUNT * 4) - 1);
-
-        //Configure topic as a subscription
-        setProperty(".topics.topic("+topicCount+").subscriptionName", "clientid:"+getTestQueueName());
-        configureTopic(getName(), (MAX_QUEUE_MESSAGE_COUNT - 1));
-
-
-
-        //Start the broker
-        startBroker();
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, true);
-    }
-
-
-//
-//    public void testMerge() throws ConfigurationException, AMQException
-//    {
-//
-//        AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(getName()+":stockSubscription"), false, new AMQShortString("testowner"),
-//                                                    false, false, _virtualHost, null);
-//
-//        _virtualHost.getQueueRegistry().registerQueue(queue);
-//        Exchange defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange();
-//        _virtualHost.getBindingFactory().addBinding(getName(), queue, defaultExchange, null);
-//
-//
-//        Exchange topicExchange = _virtualHost.getExchangeRegistry().getExchange(ExchangeDefaults.TOPIC_EXCHANGE_NAME);
-//        _virtualHost.getBindingFactory().addBinding("stocks.nyse.orcl", queue, topicExchange, null);
-//
-//        TopicConfig config = queue.getConfiguration().getConfiguration(TopicConfig.class.getName());
-//
-//        assertNotNull("Queue should have topic configuration bound to it.", config);
-//        assertEquals("Configuration name not correct", getName() + ":stockSubscription", config.getSubscriptionName());
-//
-//        ConfigurationPlugin scdConfig = queue.getConfiguration().getConfiguration(SlowConsumerDetectionQueueConfiguration.class.getName());
-//        if (scdConfig instanceof org.apache.qpid.server.configuration.plugin.SlowConsumerDetectionQueueConfiguration)
-//        {
-//            System.err.println("********************** scd is a SlowConsumerDetectionQueueConfiguration.");
-//        }
-//        else
-//        {
-//            System.err.println("********************** Test SCD "+SlowConsumerDetectionQueueConfiguration.class.getClassLoader());
-//            System.err.println("********************** Broker SCD "+scdConfig.getClass().getClassLoader());
-//                 System.err.println("********************** Broker SCD "+scdConfig.getClass().isAssignableFrom(SlowConsumerDetectionQueueConfiguration.class));
-//            System.err.println("********************** is a "+scdConfig.getClass());
-//        }
-//
-//        assertNotNull("Queue should have scd configuration bound to it.", scdConfig);
-//        assertEquals("MessageCount is not correct", 10 , ((SlowConsumerDetectionQueueConfiguration)scdConfig).getMessageCount());
-//        assertEquals("Policy is not correct", TopicDeletePolicy.class.getName() , ((SlowConsumerDetectionQueueConfiguration)scdConfig).getPolicy().getClass().getName());
-//    }
-
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/SubscriptionTest.java b/java/systests/src/main/java/org/apache/qpid/systest/SubscriptionTest.java
deleted file mode 100644
index 9e9375fd44..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/systest/SubscriptionTest.java
+++ /dev/null
@@ -1,146 +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.systest;
-
-import org.apache.commons.configuration.ConfigurationException;
-
-import javax.jms.Session;
-import javax.naming.NamingException;
-import java.io.IOException;
-
-/**
- * Test SCD when configured with Subscription details.
- *
- * We run the subscription based tests here to validate that the
- * subscriptionname value is correctly associated with the subscription.
- *
- *
- */
-public class SubscriptionTest extends TestingBaseCase
-{
-    private int _count=0;
-    protected String CONFIG_SECTION = ".topics.topic";
-
-    /**
-     * Add configuration for the queue that relates just to this test.
-     * We use the getTestQueueName() as our subscription. To ensure the
-     * config sections do not overlap we identify each section with a _count
-     * value.
-     *
-     * This would allow each test to configure more than one section.
-     *
-     * @param property to set
-     * @param value the value to set
-     * @param deleteDurable should deleteDurable be set.
-     * @throws NamingException
-     * @throws IOException
-     * @throws ConfigurationException
-     */
-    public void setConfig(String property, String value, boolean deleteDurable) throws NamingException, IOException, ConfigurationException
-    {
-        setProperty(CONFIG_SECTION + "("+_count+").subscriptionName", "clientid:"+getTestQueueName());
-
-        setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." +
-                    "policy.name", "TopicDelete");
-
-        setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." +
-                    property, value);
-
-        if (deleteDurable)
-        {
-            setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." +
-                        "policy.topicdelete.delete-persistent", "");
-        }
-        _count++;
-    }
-
-
-    /**
-     * Test that setting messageCount takes affect on a durable Consumer
-     *
-     * Ensure we set the delete-persistent option
-     *
-     * We send 10 messages and disconnect at 9
-     *
-     * @throws Exception
-     */
-
-    public void testTopicDurableConsumerMessageCount() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        setConfig("messageCount", String.valueOf(MAX_QUEUE_MESSAGE_COUNT - 1), true);
-
-        //Start the broker
-        startBroker();
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, true);
-    }
-
-    /**
-     * Test that setting depth has an effect on durable consumer topics
-     *
-     * Ensure we set the delete-persistent option
-     *
-     * Sets the message size for the test
-     * Sets the depth to be 9 * the depth
-     * Ensure that sending 10 messages causes the disconnection
-     *
-     * @throws Exception
-     */
-    public void testTopicDurableConsumerMessageSize() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        setConfig("depth", String.valueOf(MESSAGE_SIZE * 9), true);
-
-        //Start the broker
-        startBroker();
-
-        setMessageSize(MESSAGE_SIZE);
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, true);
-    }
-
-    /**
-     * Test that setting messageAge has an effect on topics
-     *
-     * Ensure we set the delete-persistent option
-     *
-     * Sets the messageAge to be 1/5 the disconnection wait timeout (or 1sec)
-     * Send 10 messages and then ensure that we get disconnected as we will
-     * wait for the full timeout.
-     *
-     * @throws Exception
-     */
-    public void testTopicDurableConsumerMessageAge() throws Exception
-    {
-        MAX_QUEUE_MESSAGE_COUNT = 10;
-
-        setConfig("messageAge", String.valueOf(DISCONNECTION_WAIT / 5), true);
-
-        //Start the broker
-        startBroker();
-
-        topicConsumer(Session.AUTO_ACKNOWLEDGE, true);
-    }
-
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/TestingBaseCase.java b/java/systests/src/main/java/org/apache/qpid/systest/TestingBaseCase.java
deleted file mode 100644
index 86c9462fc9..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/systest/TestingBaseCase.java
+++ /dev/null
@@ -1,240 +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.systest;
-
-import org.apache.commons.configuration.ConfigurationException;
-
-import org.apache.qpid.AMQException;
-import org.apache.qpid.jms.ConnectionListener;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-import javax.jms.Connection;
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.Topic;
-import javax.naming.NamingException;
-import java.io.IOException;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-public class TestingBaseCase extends QpidBrokerTestCase implements ExceptionListener, ConnectionListener
-{
-
-    private Topic _destination;
-    protected CountDownLatch _disconnectionLatch = new CountDownLatch(1);
-    protected int MAX_QUEUE_MESSAGE_COUNT;
-    protected int MESSAGE_SIZE = DEFAULT_MESSAGE_SIZE;
-
-    private Thread _publisher;
-    protected static final long DISCONNECTION_WAIT = 5;
-    protected Exception _publisherError = null;
-    protected JMSException _connectionException = null;
-    private static final long JOIN_WAIT = 5000;
-
-    @Override
-    public void setUp() throws Exception
-    {
-
-        setConfigurationProperty("virtualhosts.virtualhost."
-                                 + getConnectionURL().getVirtualHost().substring(1) +
-                                 ".slow-consumer-detection.delay", "1");
-
-        setConfigurationProperty("virtualhosts.virtualhost."
-                                 + getConnectionURL().getVirtualHost().substring(1) +
-                                 ".slow-consumer-detection.timeunit", "SECONDS");
-
-    }
-
-
-    protected void setProperty(String property, String value) throws NamingException, IOException, ConfigurationException
-    {
-        setConfigurationProperty("virtualhosts.virtualhost." +
-                                 getConnectionURL().getVirtualHost().substring(1) +
-                                 property, value);
-    }
-
-
-    /**
-     * Create and start an asynchrounous publisher that will send MAX_QUEUE_MESSAGE_COUNT
-     * messages to the provided destination. Messages are sent in a new connection
-     * on a transaction. Any error is captured and the test is signalled to exit.
-     *
-     * @param destination
-     */
-    private void startPublisher(final Destination destination)
-    {
-        _publisher = new Thread(new Runnable()
-        {
-
-            public void run()
-            {
-                try
-                {
-                    Connection connection = getConnection();
-                    Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
-
-                    MessageProducer publisher = session.createProducer(destination);
-
-                    for (int count = 0; count < MAX_QUEUE_MESSAGE_COUNT; count++)
-                    {
-                        publisher.send(createNextMessage(session, count));
-                        session.commit();
-                    }
-                }
-                catch (Exception e)
-                {
-                    _publisherError = e;
-                    _disconnectionLatch.countDown();
-                }
-            }
-        });
-
-        _publisher.start();
-    }
-
-
-
-    /**
-     * Perform the Main test of a topic Consumer with the given AckMode.
-     *
-     * Test creates a new connection and sets up the connection to prevent
-     * failover
-     *
-     * A new consumer is connected and started so that it will prefetch msgs.
-     *
-     * An asynchrounous publisher is started to fill the broker with messages.
-     *
-     * We then wait to be notified of the disconnection via the ExceptionListener
-     *
-     * 0-10 does not have the same notification paths but sync() apparently should
-     * give us the exception, currently it doesn't, so the test is excluded from 0-10
-     *
-     * We should ensure that this test has the same path for all protocol versions.
-     *
-     * Clients should not have to modify their code based on the protocol in use.
-     *
-     * @param ackMode @see javax.jms.Session
-     *
-     * @throws Exception
-     */
-    protected void topicConsumer(int ackMode, boolean durable) throws Exception
-    {
-        Connection connection = getConnection();
-
-        connection.setExceptionListener(this);
-
-        Session session = connection.createSession(ackMode == Session.SESSION_TRANSACTED, ackMode);
-
-        _destination = session.createTopic(getName());
-
-        MessageConsumer consumer;
-
-        if (durable)
-        {
-            consumer = session.createDurableSubscriber(_destination, getTestQueueName());
-        }
-        else
-        {
-            consumer = session.createConsumer(_destination);
-        }
-
-        connection.start();
-
-        // Start the consumer pre-fetching
-        // Don't care about response as we will fill the broker up with messages
-        // after this point and ensure that the client is disconnected at the
-        // right point.
-        consumer.receiveNoWait();
-        startPublisher(_destination);
-
-        boolean disconnected = _disconnectionLatch.await(DISCONNECTION_WAIT, TimeUnit.SECONDS);
-        
-        assertTrue("Client was not disconnected", disconnected);
-        assertTrue("Client was not disconnected.", _connectionException != null);
-
-        Exception linked = _connectionException.getLinkedException();
-
-        _publisher.join(JOIN_WAIT);
-
-        assertFalse("Publisher still running", _publisher.isAlive());
-
-        //Validate publishing occurred ok
-        if (_publisherError != null)
-        {
-            throw _publisherError;
-        }
-
-        // NOTE these exceptions will need to be modeled so that they are not
-        // 0-8 specific. e.g. JMSSessionClosedException
-
-        assertNotNull("No error received onException listener.", _connectionException);
-
-        assertNotNull("No linked exception set on:" + _connectionException.getMessage(), linked);
-
-        assertTrue("Incorrect linked exception received.", linked instanceof AMQException);
-
-        AMQException amqException = (AMQException) linked;
-
-        assertEquals("Channel was not closed with correct code.", AMQConstant.RESOURCE_ERROR, amqException.getErrorCode());
-    }
-
-
-    // Exception Listener
-
-    public void onException(JMSException e)
-    {
-        _connectionException = e;
-
-        e.printStackTrace();
-
-        _disconnectionLatch.countDown();
-    }
-
-    /// Connection Listener
-
-    public void bytesSent(long count)
-    {
-    }
-
-    public void bytesReceived(long count)
-    {
-    }
-
-    public boolean preFailover(boolean redirect)
-    {
-        // Prevent Failover
-        return false;
-    }
-
-    public boolean preResubscribe()
-    {
-        return false;
-    }
-
-    public void failoverComplete()
-    {
-    }
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/TopicTest.java b/java/systests/src/main/java/org/apache/qpid/systest/TopicTest.java
deleted file mode 100644
index 09c849cfde..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/systest/TopicTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.systest;
-
-import org.apache.commons.configuration.ConfigurationException;
-
-import javax.naming.NamingException;
-import java.io.IOException;
-
-/**
- * This Topic test extends the Global queue test so it will run all the topic
- * and subscription tests.
- *
- * We redefine the CONFIG_SECTION here so that the configuration is written
- * against a topic element.
- *
- * To complete the migration to testing 'topic' elements we also override
- * the setConfig to use the test name as the topic name.
- *
- */
-public class TopicTest extends GlobalQueuesTest
-{
-    private int _count=0;
-
-    @Override
-    public void setUp() throws Exception
-    {
-        CONFIG_SECTION = ".topics.topic";
-        super.setUp();
-    }
-
-    /**
-     * Add configuration for the queue that relates just to this test.
-     * We use the getTestQueueName() as our subscription. To ensure the
-     * config sections do not overlap we identify each section with a _count
-     * value.
-     *
-     * This would allow each test to configure more than one section.
-     *
-     * @param property to set
-     * @param value the value to set
-     * @param deleteDurable should deleteDurable be set.
-     * @throws NamingException
-     * @throws IOException
-     * @throws ConfigurationException
-     */
-    @Override
-    public void setConfig(String property, String value, boolean deleteDurable) throws NamingException, IOException, ConfigurationException
-    {
-        setProperty(CONFIG_SECTION + "("+_count+").name", getName());
-
-        setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." +
-                    "policy.name", "TopicDelete");
-
-        setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." +
-                    property, value);
-
-        if (deleteDurable)
-        {
-            setProperty(CONFIG_SECTION + "("+_count+").slow-consumer-detection." +
-                        "policy.topicdelete.delete-persistent", "");
-        }
-        _count++;
-    }
-
-    
-}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
new file mode 100644
index 0000000000..954208e78e
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/BrokerManagementTest.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.common.mbeans.ManagedExchange;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+/**
+ * Tests the JMX API for the Managed Broker.
+ *
+ */
+public class BrokerManagementTest extends QpidBrokerTestCase
+{
+    private static final String VIRTUAL_HOST = "test";
+
+    /**
+     * JMX helper.
+     */
+    private JMXTestUtils _jmxUtils;
+    private ManagedBroker _managedBroker;
+
+    public void setUp() throws Exception
+    {
+        _jmxUtils = new JMXTestUtils(this);
+        _jmxUtils.setUp();
+        super.setUp();
+        _jmxUtils.open();
+        _managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
+    }
+
+    public void tearDown() throws Exception
+    {
+        if (_jmxUtils != null)
+        {
+            _jmxUtils.close();
+        }
+        super.tearDown();
+    }
+
+    /**
+     * Tests queue creation/deletion also verifying the automatic binding to the default exchange.
+     */
+    public void testCreateQueueAndDeletion() throws Exception
+    {
+        final String queueName = getTestQueueName();
+        final ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString());
+
+        // Check that bind does not exist before queue creation
+        assertFalse("Binding to " + queueName + " should not exist in default exchange before queue creation",
+                     defaultExchange.bindings().containsKey(new String[] {queueName}));
+
+        _managedBroker.createNewQueue(queueName, "testowner", true);
+
+        // Ensure the queue exists
+        assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName));
+        assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName));
+
+        // Now verify that the default exchange has been bound.
+        assertTrue("Binding to " + queueName + " should exist in default exchange after queue creation",
+                     defaultExchange.bindings().containsKey(new String[] {queueName}));
+
+        // Now delete the queue
+        _managedBroker.deleteQueue(queueName);
+
+        // Finally ensure that the binding has been removed.
+        assertFalse("Binding to " + queueName + " should not exist in default exchange after queue deletion",
+                defaultExchange.bindings().containsKey(new String[] {queueName}));
+    }
+
+    /**
+     * Tests exchange creation/deletion via JMX API.
+     */
+    public void testCreateExchangeAndUnregister() throws Exception
+    {
+        String exchangeName = getTestName();
+        _managedBroker.createNewExchange(exchangeName, "topic", true);
+
+        ManagedExchange exchange = _jmxUtils.getManagedExchange(exchangeName);
+        assertNotNull("Exchange should exist", exchange);
+
+        _managedBroker.unregisterExchange(exchangeName);
+    }
+
+    /**
+     * Tests that it is disallowed to unregister the default exchange.
+     */
+    public void testUnregisterOfDefaultExchangeDisallowed() throws Exception
+    {
+        String defaultExchangeName = ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString();
+
+        ManagedExchange defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName);
+        assertNotNull("Exchange should exist", defaultExchange);
+        try
+        {
+            _managedBroker.unregisterExchange(defaultExchangeName);
+            fail("Exception not thrown");
+        }
+        catch (UnsupportedOperationException e)
+        {
+            // PASS
+            assertEquals("'<>' is a reserved exchange and can't be deleted", e.getMessage());
+        }
+        defaultExchange = _jmxUtils.getManagedExchange(defaultExchangeName);
+        assertNotNull("Exchange should exist", defaultExchange);
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
new file mode 100644
index 0000000000..28d7bf4aed
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ConnectionManagementTest.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.management.JMException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularData;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+public class ConnectionManagementTest extends QpidBrokerTestCase
+{
+    private static final String VIRTUAL_HOST_NAME = "test";
+
+    private JMXTestUtils _jmxUtils;
+    private Connection _connection;
+
+    public void setUp() throws Exception
+    {
+        _jmxUtils = new JMXTestUtils(this);
+        _jmxUtils.setUp(); // modifies broker config therefore must be done before super.setUp()
+        super.setUp();
+        _jmxUtils.open();
+    }
+
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            if (_jmxUtils != null)
+            {
+                _jmxUtils.close();
+            }
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testNumberOfManagedConnectionsMatchesNumberOfClientConnections() throws Exception
+    {
+        assertEquals("Expected no managed connections", 0, getManagedConnections().size());
+
+        _connection = getConnection();
+        assertEquals("Expected one managed connection", 1, getManagedConnections().size());
+
+        _connection.close();
+        assertEquals("Expected no managed connections after client connection closed", 0, getManagedConnections().size());
+    }
+
+    public void testGetAttributes() throws Exception
+    {
+        _connection = getConnection();
+        final ManagedConnection mBean = getConnectionMBean();
+
+        checkAuthorisedId(mBean);
+        checkClientVersion(mBean);
+        checkClientId(mBean);
+    }
+
+    public void testNonTransactedSession() throws Exception
+    {
+        _connection = getConnection();
+
+        boolean transactional = false;
+        boolean flowBlocked = false;
+
+        _connection.createSession(transactional, Session.AUTO_ACKNOWLEDGE);
+
+        final ManagedConnection mBean = getConnectionMBean();
+        final CompositeDataSupport row = getTheOneChannelRow(mBean);
+        assertChannelRowData(row, 0, transactional, flowBlocked);
+    }
+
+    public void testTransactedSessionWithUnackMessages() throws Exception
+    {
+        _connection = getConnection();
+        _connection.start();
+
+        boolean transactional = true;
+        int numberOfMessages = 2;
+        final Session session = _connection.createSession(transactional, Session.SESSION_TRANSACTED);
+        final Destination destination = session.createQueue(getTestQueueName());
+        final MessageConsumer consumer = session.createConsumer(destination);
+
+        sendMessage(session, destination, numberOfMessages);
+        receiveMessagesWithoutCommit(consumer, numberOfMessages);
+
+        final ManagedConnection mBean = getConnectionMBean();
+        final CompositeDataSupport row = getTheOneChannelRow(mBean);
+        boolean flowBlocked = false;
+        assertChannelRowData(row, numberOfMessages, transactional, flowBlocked);
+
+        // check that commit advances the lastIoTime
+        final Date initialLastIOTime = mBean.getLastIoTime();
+        session.commit();
+        assertTrue("commit should have caused last IO time to advance", mBean.getLastIoTime().after(initialLastIOTime));
+
+        // check that channels() now returns one session with no unacknowledged messages
+        final CompositeDataSupport rowAfterCommit = getTheOneChannelRow(mBean);
+        final Number unackCountAfterCommit = (Number) rowAfterCommit.get(ManagedConnection.UNACKED_COUNT);
+        assertEquals("Unexpected number of unacknowledged messages", 0, unackCountAfterCommit);
+    }
+
+
+    public void testProducerFlowBlocked() throws Exception
+    {
+        _connection = getConnection();
+        _connection.start();
+
+        String queueName = getTestQueueName();
+        Session session = _connection.createSession(true, Session.SESSION_TRANSACTED);
+        Queue queue = session.createQueue(queueName);
+        createQueueOnBroker(session, queue);
+
+        ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        managedQueue.setFlowResumeCapacity(DEFAULT_MESSAGE_SIZE * 2l);
+        managedQueue.setCapacity(DEFAULT_MESSAGE_SIZE * 3l);
+
+        final ManagedConnection managedConnection = getConnectionMBean();
+
+        // Check that producer flow is not block before test
+        final CompositeDataSupport rowBeforeSend = getTheOneChannelRow(managedConnection);
+        assertFlowBlocked(rowBeforeSend, false);
+
+
+        // Check that producer flow does not become block too soon
+        sendMessage(session, queue, 3);
+        final CompositeDataSupport rowBeforeFull = getTheOneChannelRow(managedConnection);
+        assertFlowBlocked(rowBeforeFull, false);
+
+        // Fourth message will over-fill the queue (but as we are not sending more messages, client thread wont't block)
+        sendMessage(session, queue, 1);
+        final CompositeDataSupport rowAfterFull = getTheOneChannelRow(managedConnection);
+        assertFlowBlocked(rowAfterFull, true);
+
+        // Consume two to bring the queue down to the resume capacity
+        MessageConsumer consumer = session.createConsumer(queue);
+        assertNotNull("Could not receive first message", consumer.receive(1000));
+        assertNotNull("Could not receive second message", consumer.receive(1000));
+        session.commit();
+
+        // Check that producer flow is no longer blocked
+        final CompositeDataSupport rowAfterReceive = getTheOneChannelRow(managedConnection);
+        assertFlowBlocked(rowAfterReceive, false);
+    }
+
+    private void createQueueOnBroker(Session session, Destination destination) throws JMSException
+    {
+        session.createConsumer(destination).close(); // Create a consumer only to cause queue creation
+    }
+
+    private void assertChannelRowData(final CompositeData row, int unacknowledgedMessages, boolean isTransactional, boolean flowBlocked)
+    {
+        assertNotNull(row);
+        assertEquals("Unexpected transactional flag", isTransactional, row.get(ManagedConnection.TRANSACTIONAL));
+        assertEquals("Unexpected unacknowledged message count", unacknowledgedMessages, row.get(ManagedConnection.UNACKED_COUNT));
+        assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED));
+    }
+
+    private void assertFlowBlocked(final CompositeData row, boolean flowBlocked)
+    {
+        assertNotNull(row);
+        assertEquals("Unexpected flow blocked", flowBlocked, row.get(ManagedConnection.FLOW_BLOCKED));
+    }
+
+    private void checkAuthorisedId(ManagedConnection mBean) throws Exception
+    {
+        assertEquals("Unexpected authorized id", GUEST_USERNAME, mBean.getAuthorizedId());
+    }
+
+    private void checkClientVersion(ManagedConnection mBean) throws Exception
+    {
+        String expectedVersion = QpidProperties.getReleaseVersion();
+        assertTrue(StringUtils.isNotBlank(expectedVersion));
+
+        assertEquals("Unexpected version", expectedVersion, mBean.getVersion());
+    }
+
+    private void checkClientId(ManagedConnection mBean) throws Exception
+    {
+        String expectedClientId = _connection.getClientID();
+        assertTrue(StringUtils.isNotBlank(expectedClientId));
+
+        assertEquals("Unexpected ClientId", expectedClientId, mBean.getClientId());
+    }
+
+    private ManagedConnection getConnectionMBean()
+    {
+        List connections = getManagedConnections();
+        assertNotNull("Connection MBean is not found", connections);
+        assertEquals("Unexpected number of connection mbeans", 1, connections.size());
+        final ManagedConnection mBean = connections.get(0);
+        assertNotNull("Connection MBean is null", mBean);
+        return mBean;
+    }
+
+    private List getManagedConnections()
+    {
+        return _jmxUtils.getManagedConnections(VIRTUAL_HOST_NAME);
+    }
+
+    private CompositeDataSupport getTheOneChannelRow(final ManagedConnection mBean) throws Exception
+    {
+        TabularData channelsData = getChannelsDataWithRetry(mBean);
+
+        assertEquals("Unexpected number of rows in channel table", 1, channelsData.size());
+
+        @SuppressWarnings("unchecked")
+        final Iterator rowItr = (Iterator) channelsData.values().iterator();
+        final CompositeDataSupport row = rowItr.next();
+        return row;
+    }
+
+    private void receiveMessagesWithoutCommit(final MessageConsumer consumer, int numberOfMessages) throws Exception
+    {
+        for (int i = 0; i < numberOfMessages; i++)
+        {
+            final Message m = consumer.receive(1000l);
+            assertNotNull("Message " + i + " is not received", m);
+        }
+    }
+
+    private TabularData getChannelsDataWithRetry(final ManagedConnection mBean)
+            throws IOException, JMException
+    {
+        TabularData channelsData = mBean.channels();
+        int retries = 0;
+        while(channelsData.size() == 0 && retries < 5)
+        {
+            sleep();
+            channelsData = mBean.channels();
+            retries++;
+        }
+        return channelsData;
+    }
+
+    private void sleep()
+    {
+        try
+        {
+            Thread.sleep(50);
+        }
+        catch (InterruptedException ie)
+        {
+            Thread.currentThread().interrupt();
+        }
+    }}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
new file mode 100644
index 0000000000..3c3bbdca41
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/LoggingManagementTest.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import java.io.File;
+import java.util.List;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import org.apache.qpid.management.common.mbeans.LoggingManagement;
+import org.apache.qpid.server.logging.log4j.LoggingManagementFacadeTest;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.util.FileUtils;
+import org.apache.qpid.util.LogMonitor;
+
+/**
+ * System test for Logging Management.  These tests rely on value set within
+ * test-profiles/log4j-test.xml.
+ *
+ * @see LoggingManagementMBeanTest
+ * @see LoggingManagementFacadeTest
+ *
+ */
+public class LoggingManagementTest extends QpidBrokerTestCase
+{
+    private JMXTestUtils _jmxUtils;
+    private LoggingManagement _loggingManagement;
+    private LogMonitor _monitor;
+
+    public void setUp() throws Exception
+    {
+        _jmxUtils = new JMXTestUtils(this);
+        _jmxUtils.setUp();
+
+        // System test normally run with log for4j test config from beneath test-profiles.   We need to
+        // copy it as some of our tests write to this file.
+
+        File tmpLogFile = File.createTempFile("log4j" + "." + getName(), ".xml");
+        tmpLogFile.deleteOnExit();
+        FileUtils.copy(getBrokerCommandLog4JFile(), tmpLogFile);
+        setBrokerCommandLog4JFile(tmpLogFile);
+
+        super.setUp();
+        _jmxUtils.open();
+
+        _loggingManagement = _jmxUtils.getLoggingManagement();
+        _monitor = new LogMonitor(_outputFile);
+    }
+
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            if (_jmxUtils != null)
+            {
+                _jmxUtils.close();
+            }
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testViewEffectiveRuntimeLoggerLevels() throws Exception
+    {
+        final String qpidMainLogger = "org.apache.qpid";
+
+        TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels();
+        final CompositeData row = table.get(new String[] {qpidMainLogger} );
+        assertChannelRow(row, qpidMainLogger, "DEBUG");
+    }
+
+    public void testViewConfigFileLoggerLevels() throws Exception
+    {
+        final String operationalLoggingLogger = "qpid.message";
+
+        TabularData table = _loggingManagement.viewConfigFileLoggerLevels();
+        final CompositeData row = table.get(new String[] {operationalLoggingLogger} );
+        assertChannelRow(row, operationalLoggingLogger, "INFO");
+    }
+
+    public void testTurnOffOrgApacheQpidAtRuntime() throws Exception
+    {
+        final String logger = "org.apache.qpid";
+        _monitor.markDiscardPoint();
+        _loggingManagement.setRuntimeLoggerLevel(logger, "OFF");
+
+        List matches = _monitor.waitAndFindMatches("Setting level to OFF for logger 'org.apache.qpid'", 5000);
+        assertEquals(1, matches.size());
+
+        TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels();
+        final CompositeData row1 = table.get(new String[] {logger} );
+        assertChannelRow(row1, logger, "OFF");
+    }
+
+    public void testChangesToConfigFileBecomeEffectiveAfterReload() throws Exception
+    {
+        final String operationalLoggingLogger  = "qpid.message";
+        assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO");
+
+        _monitor.markDiscardPoint();
+        _loggingManagement.setConfigFileLoggerLevel(operationalLoggingLogger, "OFF");
+
+        List matches = _monitor.waitAndFindMatches("Setting level to OFF for logger 'qpid.message'", 5000);
+        assertEquals(1, matches.size());
+
+        assertEffectiveLoggingLevel(operationalLoggingLogger, "INFO");
+
+        _loggingManagement.reloadConfigFile();
+
+        assertEffectiveLoggingLevel(operationalLoggingLogger, "OFF");
+    }
+
+    private void assertEffectiveLoggingLevel(String operationalLoggingLogger, String expectedLevel)
+    {
+        TabularData table = _loggingManagement.viewEffectiveRuntimeLoggerLevels();
+        final CompositeData row1 = table.get(new String[] {operationalLoggingLogger} );
+        assertChannelRow(row1, operationalLoggingLogger, expectedLevel);
+    }
+
+    private void assertChannelRow(final CompositeData row, String logger, String level)
+    {
+        assertNotNull("No row for  " + logger, row);
+        assertEquals("Unexpected logger name", logger, row.get(LoggingManagement.LOGGER_NAME));
+        assertEquals("Unexpected level", level, row.get(LoggingManagement.LOGGER_LEVEL));
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
new file mode 100644
index 0000000000..47b38381c5
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementActorLoggingTest.java
@@ -0,0 +1,480 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.management.common.mbeans.ManagedExchange;
+import org.apache.qpid.server.logging.AbstractTestLogging;
+import org.apache.qpid.server.logging.subjects.AbstractTestLogSubject;
+import org.apache.qpid.test.utils.JMXTestUtils;
+
+import javax.jms.Connection;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.management.JMException;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test class to test if any change in the broker JMX code is affesting the management console
+ * There are some hardcoding of management feature names and parameter names to create a customized
+ * look in the console.
+ */
+public class ManagementActorLoggingTest extends AbstractTestLogging
+{
+    private JMXTestUtils _jmxUtils;
+    private boolean _closed = false;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        _jmxUtils = new JMXTestUtils(this);
+        _jmxUtils.setUp();
+        super.setUp();
+        _jmxUtils.open();
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        if(!_closed)
+        {
+            _jmxUtils.close();
+        }
+        super.tearDown();
+    }
+
+    /**
+     * Description:
+     * When a connected client has its connection closed via the Management Console this will be logged as a CON-1002 message.
+     * Input:
+     *
+     * 1. Running Broker
+     * 2. Connected Client
+     * 3. Connection is closed via Management Console
+     * Output:
+     *
+     *  CON-1002 : Close
+     *
+     * Validation Steps:
+     * 4. The CON ID is correct
+     * 5. This must be the last CON message for the Connection
+     * 6. It must be preceded by a CON-1001 for this Connection
+     *
+     * @throws Exception           - {@see ManagedConnection.closeConnection and #getConnection}
+     * @throws java.io.IOException - if there is a problem reseting the log monitor
+     */
+    public void testConnectionCloseViaManagement() throws IOException, Exception
+    {
+        //Create a connection to the broker
+        Connection connection = getConnection();
+
+        // Monitor the connection for an exception being thrown
+        // this should be a DisconnectionException but it is not this tests
+        // job to valiate that. Only use the exception as a synchronisation
+        // to check the log file for the Close message
+        final CountDownLatch exceptionReceived = new CountDownLatch(1);
+        connection.setExceptionListener(new ExceptionListener()
+        {
+            public void onException(JMSException e)
+            {
+                //Failover being attempted.
+                exceptionReceived.countDown();
+            }
+        });
+
+        //Remove the connection close from any 0-10 connections
+        _monitor.markDiscardPoint();
+
+        // Get a managedConnection
+        ManagedConnection mangedConnection = _jmxUtils.getManagedObject(ManagedConnection.class, "org.apache.qpid:type=VirtualHost.Connection,*");
+
+        //Close the connection
+        mangedConnection.closeConnection();
+
+        //Wait for the connection to close
+        assertTrue("Timed out waiting for conneciton to report close",
+                   exceptionReceived.await(2, TimeUnit.SECONDS));
+
+        //Validate results
+        List results = waitAndFindMatches("CON-1002");
+
+        assertEquals("Unexpected Connection Close count", 1, results.size());
+    }
+
+    /**
+     * Description:
+     * Exchange creation is possible from the Management Console.
+     * When an exchanged is created in this way then a EXH-1001 create message
+     * is expected to be logged.
+     * Input:
+     *
+     * 1. Running broker
+     * 2. Connected Management Console
+     * 3. Exchange Created via Management Console
+     * Output:
+     *
+     * EXH-1001 : Create : [Durable] Type: Name:
+     *
+     * Validation Steps:
+     * 4. The EXH ID is correct
+     * 5. The correct tags are present in the message based on the create options
+     *
+     * @throws java.io.IOException          - if there is a problem reseting the log monitor
+     * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue}
+     */
+    public void testCreateExchangeDirectTransientViaManagementConsole() throws IOException, JMException
+    {
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createExchange("test", getName(), "direct", false);
+
+        // Validate
+
+        //1 - ID is correct
+        List results = waitAndFindMatches("EXH-1001");
+
+        assertEquals("More than one exchange creation found", 1, results.size());
+
+        String log = getLogMessage(results, 0);
+
+        // Validate correct exchange name
+        assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName()));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+    }
+
+    public void testCreateExchangeTopicTransientViaManagementConsole() throws IOException, JMException
+    {
+        //Remove any previous exchange declares
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createExchange("test", getName(), "topic", false);
+
+        // Validate
+
+        //1 - ID is correct
+        List results = waitAndFindMatches("EXH-1001");
+
+        assertEquals("More than one exchange creation found", 1, results.size());
+
+        String log = getLogMessage(results, 0);
+
+        // Validate correct exchange name
+        assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName()));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+
+    }
+
+    public void testCreateExchangeFanoutTransientViaManagementConsole() throws IOException, JMException
+    {
+        //Remove any previous exchange declares
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createExchange("test", getName(), "fanout", false);
+
+        // Validate
+
+        //1 - ID is correct
+        List results = waitAndFindMatches("EXH-1001");
+
+        assertEquals("More than one exchange creation found", 1, results.size());
+
+        String log = getLogMessage(results, 0);
+
+        // Validate correct exchange name
+        assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName()));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+
+    }
+
+    public void testCreateExchangeHeadersTransientViaManagementConsole() throws IOException, JMException
+    {
+        //Remove any previous exchange declares
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createExchange("test", getName(), "headers", false);
+
+        // Validate
+
+        //1 - ID is correct
+        List results = waitAndFindMatches("EXH-1001");
+
+        assertEquals("More than one exchange creation found", 1, results.size());
+
+        String log = getLogMessage(results, 0);
+
+        // Validate correct exchange name
+        assertTrue("Incorrect exchange name created:" + log, log.endsWith(getName()));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+
+    }
+
+    /**
+     * Description:
+     * Queue creation is possible from the Management Console. When a queue is created in this way then a QUE-1001 create message is expected to be logged.
+     * Input:
+     *
+     * 1. Running broker
+     * 2. Connected Management Console
+     * 3. Queue Created via Management Console
+     * Output:
+     *
+     *  QUE-1001 : Create : Transient Owner:
+     *
+     * Validation Steps:
+     * 4. The QUE ID is correct
+     * 5. The correct tags are present in the message based on the create options
+     *
+     * @throws java.io.IOException          - if there is a problem reseting the log monitor
+     * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue}
+     */
+    public void testCreateQueueTransientViaManagementConsole() throws IOException, JMException
+    {
+        //Remove any previous queue declares
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createQueue("test", getName(), null, false);
+
+        // Validate
+
+        List results = waitAndFindMatches("QUE-1001");
+
+        assertEquals("More than one queue creation found", 1, results.size());
+
+        String log = getLogMessage(results, 0);
+
+        // Validate correct queue name
+        String subject = fromSubject(log);
+        assertEquals("Incorrect queue name created", getName(), AbstractTestLogSubject.getSlice("qu", subject));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+    }
+
+    /**
+     * Description:
+     * The ManagementConsole can be used to delete a queue. When this is done a QUE-1002 Deleted message must be logged.
+     * Input:
+     *
+     * 1. Running Broker
+     * 2. Queue created on the broker with no subscribers
+     * 3. Management Console connected
+     * 4. Queue is deleted via Management Console
+     * Output:
+     *
+     *  QUE-1002 : Deleted
+     *
+     * Validation Steps:
+     * 5. The QUE ID is correct
+     *
+     * @throws java.io.IOException          - if there is a problem reseting the log monitor
+     * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.deleteQueue}
+     */
+    public void testQueueDeleteViaManagementConsole() throws IOException, JMException
+    {
+        //Remove any previous queue declares
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createQueue("test", getName(), null, false);
+
+        ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test");
+
+        managedBroker.deleteQueue(getName());
+
+        List results = waitAndFindMatches("QUE-1002");
+
+        assertEquals("More than one queue deletion found", 1, results.size());
+
+        String log = getLog(results.get(0));
+
+        // Validate correct binding
+        String subject = fromSubject(log);
+        assertEquals("Incorrect queue named in delete", getName(), AbstractTestLogSubject.getSlice("qu", subject));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+
+    }
+
+    /**
+     * Description:
+     * The binding of a Queue and an Exchange is done via a Binding. When this Binding is created via the Management Console a BND-1001 Create message will be logged.
+     * Input:
+     *
+     * 1. Running Broker
+     * 2. Connected Management Console
+     * 3. Use Management Console to perform binding
+     * Output:
+     *
+     *  BND-1001 : Create
+     *
+     * Validation Steps:
+     * 4. The BND ID is correct
+     * 5. This will be the first message for the given binding
+     *
+     * @throws java.io.IOException          - if there is a problem reseting the log monitor
+     * @throws javax.management.JMException - {@see #createQueue and ManagedExchange.createNewBinding}
+     */
+    public void testBindingCreateOnDirectViaManagementConsole() throws IOException, JMException
+    {
+        //Remove any previous queue declares
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createQueue("test", getName(), null, false);
+
+        ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.direct");
+
+        managedExchange.createNewBinding(getName(), getName());
+
+        List results = waitAndFindMatches("BND-1001");
+
+        assertEquals("Unexpected number of bindings logged", 2, results.size());
+
+        String log = getLogMessage(results, 0);
+
+        // Validate correct binding
+        String subject = fromSubject(log);
+        assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject));
+        assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+    }
+
+    public void testBindingCreateOnTopicViaManagementConsole() throws IOException, JMException
+    {
+        //Remove any previous queue declares
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createQueue("test", getName(), null, false);
+
+        ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.topic");
+
+        managedExchange.createNewBinding(getName(), getName());
+
+        List results = waitAndFindMatches("BND-1001");
+
+        assertEquals("Unexpected number of bindings logged", 2, results.size());
+
+        String log = getLogMessage(results, 0);
+
+        // Validate correct binding
+        String subject = fromSubject(log);
+        assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject));
+        assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+    }
+
+    public void testBindingCreateOnFanoutViaManagementConsole() throws IOException, JMException
+    {
+        //Remove any previous queue declares
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createQueue("test", getName(), null, false);
+
+        ManagedExchange managedExchange = _jmxUtils.getManagedExchange("amq.fanout");
+
+        managedExchange.createNewBinding(getName(), getName());
+
+        List results = waitAndFindMatches("BND-1001");
+
+        assertEquals("Unexpected number of bindings logged", 2, results.size());
+
+        String log = getLogMessage(results, 0);
+
+        // Validate correct binding
+        String subject = fromSubject(log);
+        assertEquals("Incorrect queue named in create", getName(), AbstractTestLogSubject.getSlice("qu", subject));
+        assertEquals("Incorrect routing key in create", getName(), AbstractTestLogSubject.getSlice("rk", subject));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+    }
+
+    /**
+     * Description:
+     * Bindings can be deleted so that a queue can be rebound with a different set of values. This can be performed via the Management Console
+     * Input:
+     *
+     * 1. Running Broker
+     * 2. Management Console connected
+     * 3. Management Console is used to perform unbind.
+     * Output:
+     *
+     *  BND-1002 : Deleted
+     *
+     * Validation Steps:
+     * 4. The BND ID is correct
+     * 5. There must have been a BND-1001 Create message first.
+     * 6. This will be the last message for the given binding
+     *
+     * @throws java.io.IOException          - if there is a problem reseting the log monitor or an issue with the JMX Connection
+     * @throws javax.management.JMException - {@see #createExchange and ManagedBroker.unregisterExchange}
+     */
+    public void testUnRegisterExchangeViaManagementConsole() throws IOException, JMException
+    {
+        //Remove any previous queue declares
+        _monitor.markDiscardPoint();
+
+        _jmxUtils.createExchange("test", getName(), "direct", false);
+
+        ManagedBroker managedBroker = _jmxUtils.getManagedBroker("test");
+
+        managedBroker.unregisterExchange(getName());
+
+        List results = waitAndFindMatches("EXH-1002");
+
+        assertEquals("More than one exchange deletion found", 1, results.size());
+
+        String log = getLog(results.get(0));
+
+        // Validate correct binding
+        String subject = fromSubject(log);
+        assertEquals("Incorrect exchange named in delete", "direct/" + getName(), AbstractTestLogSubject.getSlice("ex", subject));
+
+        // Validate it was a management actor.
+        String actor = fromActor(log);
+        assertTrue("Actor is not a manangement actor:" + actor, actor.startsWith("mng"));
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
new file mode 100644
index 0000000000..950b002b87
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java
@@ -0,0 +1,330 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.management.jmx;
+
+
+import org.apache.qpid.server.configuration.BrokerProperties;
+import org.apache.qpid.server.logging.AbstractTestLogging;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.apache.qpid.test.utils.TestSSLConstants;
+import org.apache.qpid.util.LogMonitor;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Management Console Test Suite
+ *
+ * The Management Console test suite validates that the follow log messages as specified in the Functional Specification.
+ *
+ * This suite of tests validate that the management console messages occur correctly and according to the following format:
+ *
+ * MNG-1001 :  Management Startup
+ * MNG-1002 : Starting :  : Listening on port 
+ * MNG-1003 : Shutting down :  : port 
+ * MNG-1004 :  Management Ready
+ * MNG-1005 :  Management Stopped
+ * MNG-1006 : Using SSL Keystore : 
+ * MNG-1007 : Open : User 
+ * MNG-1008 : Close : User 
+ */
+public class ManagementLoggingTest extends AbstractTestLogging
+{
+    private static final String MNG_PREFIX = "MNG-";
+
+    public void setUp() throws Exception
+    {
+        setLogMessagePrefix();
+
+        // We either do this here or have a null check in tearDown.
+        // As when this test is run against profiles other than java it will NPE
+        _monitor = new LogMonitor(_outputFile);
+        //We explicitly do not call super.setUp as starting up the broker is
+        //part of the test case.
+
+    }
+
+    /**
+     * Description:
+     * Using the startup configuration validate that the management startup
+     * message is logged correctly.
+     * Input:
+     * Standard configuration with management enabled
+     * Output:
+     *
+     *  MNG-1001 : Startup
+     *
+     * Constraints:
+     * This is the FIRST message logged by MNG
+     * Validation Steps:
+     *
+     * 1. The BRK ID is correct
+     * 2. This is the FIRST message logged by MNG
+     */
+    public void testManagementStartupEnabled() throws Exception
+    {
+        // This test only works on java brokers
+        if (isJavaBroker())
+        {
+            startBrokerAndCreateMonitor(true, false);
+
+            // Ensure we have received the MNG log msg.
+            waitForMessage("MNG-1001");
+
+            List results = findMatches(MNG_PREFIX);
+            // Validation
+
+            assertTrue("MNGer message not logged", results.size() > 0);
+
+            String log = getLogMessage(results, 0);
+
+            //1
+            validateMessageID("MNG-1001", log);
+
+            //2
+            //There will be 2 copies of the startup message (one via SystemOut, and one via Log4J)
+            results = findMatches("MNG-1001");
+            assertEquals("Unexpected startup message count.",
+                         2, results.size());
+
+            //3
+            assertEquals("Startup log message is not 'Startup'.", "JMX Management Startup",
+                         getMessageString(log));
+        }
+    }
+
+    /**
+     * Description:
+     * Verify that when management is disabled in the configuration file the
+     * startup message is not logged.
+     * Input:
+     * Standard configuration with management disabled
+     * Output:
+     * NO MNG messages
+     * Validation Steps:
+     *
+     * 1. Validate that no MNG messages are produced.
+     */
+    public void testManagementStartupDisabled() throws Exception
+    {
+        if (isJavaBroker())
+        {
+            startBrokerAndCreateMonitor(false, false);
+
+            List results = findMatches(MNG_PREFIX);
+            // Validation
+
+            assertEquals("MNGer messages logged", 0, results.size());
+        }
+    }
+
+    /**
+     * The two MNG-1002 messages are logged at the same time so lets test them
+     * at the same time.
+     *
+     * Description:
+     * Using the default configuration validate that the RMI Registry socket is
+     * correctly reported as being opened
+     *
+     * Input:
+     * The default configuration file
+     * Output:
+     *
+     *  MESSAGE MNG-1002 : Starting : RMI Registry : Listening on port 8999
+     *
+     * Constraints:
+     * The RMI ConnectorServer and Registry log messages do not have a prescribed order
+     * Validation Steps:
+     *
+     * 1. The MNG ID is correct
+     * 2. The specified port is the correct '8999'
+     *
+     * Description:
+     * Using the default configuration validate that the RMI ConnectorServer
+     * socket is correctly reported as being opened
+     *
+     * Input:
+     * The default configuration file
+     * Output:
+     *
+     *  MESSAGE MNG-1002 : Starting : RMI ConnectorServer : Listening on port 9099
+     *
+     * Constraints:
+     * The RMI ConnectorServer and Registry log messages do not have a prescribed order
+     * Validation Steps:
+     *
+     * 1. The MNG ID is correct
+     * 2. The specified port is the correct '9099'
+     */
+    public void testManagementStartupRMIEntries() throws Exception
+    {
+        if (isJavaBroker())
+        {
+            startBrokerAndCreateMonitor(true, false);
+
+            List results = waitAndFindMatches("MNG-1002");
+            // Validation
+
+            //There will be 4 startup messages (two via SystemOut, and two via Log4J)
+            assertEquals("Unexpected MNG-1002 message count", 4, results.size());
+
+            String log = getLogMessage(results, 0);
+
+            //1
+            validateMessageID("MNG-1002", log);
+
+            //Check the RMI Registry port is as expected
+            int mPort = getManagementPort(getPort());
+            assertTrue("RMI Registry port not as expected(" + mPort + ").:" + getMessageString(log),
+                       getMessageString(log).endsWith(String.valueOf(mPort)));
+
+            log = getLogMessage(results, 2);
+
+            //1
+            validateMessageID("MNG-1002", log);
+
+            // We expect the RMI Registry port (the defined 'management port') to be
+            // 100 lower than the JMX RMIConnector Server Port (the actual JMX server)
+            int jmxPort = mPort + JMXPORT_CONNECTORSERVER_OFFSET;
+            assertTrue("JMX RMIConnectorServer port not as expected(" + jmxPort + ").:" + getMessageString(log),
+                       getMessageString(log).endsWith(String.valueOf(jmxPort)));
+        }
+    }
+
+    /**
+     * Description:
+     * Using the default configuration with SSL enabled for the management port the SSL Keystore path should be reported via MNG-1006
+     * Input:
+     * Management SSL enabled default configuration.
+     * Output:
+     *
+     *  MESSAGE MNG-1006 : Using SSL Keystore : test_resources/ssl/keystore.jks
+     *
+     * Validation Steps:
+     *
+     * 1. The MNG ID is correct
+     * 2. The keystore path is as specified in the configuration
+     */
+    public void testManagementStartupSSLKeystore() throws Exception
+    {
+        if (isJavaBroker())
+        {
+            setSystemProperty("javax.net.debug", "ssl");
+            startBrokerAndCreateMonitor(true, true);
+
+            List results = waitAndFindMatches("MNG-1006");
+
+            assertTrue("MNGer message not logged", results.size() > 0);
+
+            String log = getLogMessage(results, 0);
+
+            //1
+            validateMessageID("MNG-1006", log);
+
+            // Validate we only have two MNG-1002 (one via stdout, one via log4j)
+            results = findMatches("MNG-1006");
+            assertEquals("Upexpected SSL Keystore message count",
+                         2, results.size());
+
+            // Validate the keystore path is as expected
+            assertTrue("SSL Keystore entry expected.:" + getMessageString(log),
+                       getMessageString(log).endsWith(TestSSLConstants.BROKER_KEYSTORE));
+        }
+    }
+
+    /**
+     * Description: Tests the management connection open/close are logged correctly.
+     *
+     * Output:
+     *
+     *  MESSAGE MNG-1007 : Open : User 
+     *  MESSAGE MNG-1008 : Close : User 
+     *
+     * Validation Steps:
+     *
+     * 1. The MNG ID is correct
+     * 2. The message and username are correct
+     */
+    public void testManagementUserOpenClose() throws Exception
+    {
+        if (isJavaBroker())
+        {
+            setSystemProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, "false");
+            startBrokerAndCreateMonitor(true, false);
+
+            final JMXTestUtils jmxUtils = new JMXTestUtils(this);
+            List openResults = null;
+            List closeResults = null;
+            try
+            {
+                jmxUtils.setUp();
+                jmxUtils.open();
+                openResults = waitAndFindMatches("MNG-1007");
+            }
+            finally
+            {
+                if (jmxUtils != null)
+                {
+                    jmxUtils.close();
+                    closeResults = waitAndFindMatches("MNG-1008");
+                }
+            }
+
+            assertNotNull("Management Open results null", openResults.size());
+            assertEquals("Management Open logged unexpected number of times", 1, openResults.size());
+
+            assertNotNull("Management Close results null", closeResults.size());
+            assertEquals("Management Close logged unexpected number of times", 1, closeResults.size());
+
+            final String openMessage = getMessageString(getLogMessage(openResults, 0));
+            assertTrue("Unexpected open message " + openMessage, openMessage.endsWith("Open : User admin"));
+            final String closeMessage = getMessageString(getLogMessage(closeResults, 0));
+            assertTrue("Unexpected close message " + closeMessage, closeMessage.endsWith("Close : User admin"));
+        }
+    }
+
+    private void startBrokerAndCreateMonitor(boolean managementEnabled, boolean useManagementSSL) throws Exception
+    {
+        TestBrokerConfiguration config = getBrokerConfiguration();
+
+        if (managementEnabled)
+        {
+            config.addJmxManagementConfiguration();
+        }
+
+        if(useManagementSSL)
+        {
+            // This test requires we have an ssl connection
+            config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_JMX_PORT, Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+
+            setSystemProperty("javax.net.ssl.keyStore", "test-profiles/test_resources/ssl/java_broker_keystore.jks");
+            setSystemProperty("javax.net.ssl.keyStorePassword", "password");
+        }
+
+        startBroker();
+
+        // Now we can create the monitor as _outputFile will now be defined
+        _monitor = new LogMonitor(_outputFile);
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
new file mode 100644
index 0000000000..0d3289d1bd
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java
@@ -0,0 +1,778 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import org.apache.commons.lang.time.FastDateFormat;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.configuration.ClientProperties;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.server.queue.NotificationCheckTest;
+import org.apache.qpid.server.queue.SimpleAMQQueueTest;
+import org.apache.qpid.test.client.destination.AddressBasedDestinationTest;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageListener;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+import javax.naming.NamingException;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tests the JMX API for the Managed Queue.
+ *
+ */
+public class QueueManagementTest extends QpidBrokerTestCase
+{
+
+    private static final Logger LOGGER = Logger.getLogger(QueueManagementTest.class);
+
+    private static final String VIRTUAL_HOST = "test";
+    private static final String TEST_QUEUE_DESCRIPTION = "my description";
+
+    private JMXTestUtils _jmxUtils;
+    private Connection _connection;
+    private Session _session;
+
+    private String _sourceQueueName;
+    private String _destinationQueueName;
+    private Destination _sourceQueue;
+    private Destination _destinationQueue;
+    private ManagedQueue _managedSourceQueue;
+    private ManagedQueue _managedDestinationQueue;
+
+    public void setUp() throws Exception
+    {
+        _jmxUtils = new JMXTestUtils(this);
+        _jmxUtils.setUp();
+
+        super.setUp();
+        _sourceQueueName = getTestQueueName() + "_src";
+        _destinationQueueName = getTestQueueName() + "_dest";
+
+        createConnectionAndSession();
+
+        _sourceQueue = _session.createQueue(_sourceQueueName);
+        _destinationQueue = _session.createQueue(_destinationQueueName);
+        createQueueOnBroker(_sourceQueue);
+        createQueueOnBroker(_destinationQueue);
+
+        _jmxUtils.open();
+
+        createManagementInterfacesForQueues();
+    }
+
+    public void tearDown() throws Exception
+    {
+        if (_jmxUtils != null)
+        {
+            _jmxUtils.close();
+        }
+        super.tearDown();
+    }
+
+    public void testQueueAttributes() throws Exception
+    {
+        Queue queue = _session.createQueue(getTestQueueName());
+        createQueueOnBroker(queue);
+
+        final String queueName = queue.getQueueName();
+
+        final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertEquals("Unexpected name", queueName, managedQueue.getName());
+        assertEquals("Unexpected queue type", "standard", managedQueue.getQueueType());
+    }
+
+    public void testExclusiveQueueHasJmsClientIdAsOwner() throws Exception
+    {
+        Queue tmpQueue = _session.createTemporaryQueue();
+
+        final String queueName = tmpQueue.getQueueName();
+
+        final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertNotNull(_connection.getClientID());
+        assertEquals("Unexpected owner", _connection.getClientID(), managedQueue.getOwner());
+    }
+
+    public void testNonExclusiveQueueHasNoOwner() throws Exception
+    {
+        Queue nonExclusiveQueue = _session.createQueue(getTestQueueName());
+        createQueueOnBroker(nonExclusiveQueue);
+
+        final String queueName = nonExclusiveQueue.getQueueName();
+
+        final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertNull("Unexpected owner", managedQueue.getOwner());
+    }
+
+    public void testSetNewQueueDescriptionOnExistingQueue() throws Exception
+    {
+        Queue queue = _session.createQueue(getTestQueueName());
+        createQueueOnBroker(queue);
+
+        final String queueName = queue.getQueueName();
+
+        final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertNull("Unexpected description", managedQueue.getDescription());
+
+        managedQueue.setDescription(TEST_QUEUE_DESCRIPTION);
+        assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
+    }
+
+    public void testNewQueueWithDescription() throws Exception
+    {
+        String queueName = getTestQueueName();
+        Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION);
+        ((AMQSession)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments);
+
+        final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
+    }
+
+    /**
+     * Requires persistent store.
+     */
+    public void testQueueDescriptionSurvivesRestart() throws Exception
+    {
+        String queueName = getTestQueueName();
+        Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION);
+
+        ((AMQSession)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments);
+
+        ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
+
+        restartBroker();
+
+        managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertEquals(TEST_QUEUE_DESCRIPTION, managedQueue.getDescription());
+    }
+
+    /**
+     * Tests queue creation with {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument.  Also tests
+     * that the attribute is exposed correctly through {@link ManagedQueue#getMaximumDeliveryCount()}.
+     */
+    public void testCreateQueueWithMaximumDeliveryCountSet() throws Exception
+    {
+        final String queueName = getName();
+        final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
+
+        final Integer deliveryCount = 1;
+        final Map arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount);
+        managedBroker.createNewQueue(queueName, null, true, arguments);
+
+        // Ensure the queue exists
+        assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName));
+        assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName));
+
+        final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertEquals("Unexpected maximum delivery count", deliveryCount, managedQueue.getMaximumDeliveryCount());
+    }
+
+    public void testCreateQueueWithAlertingThresholdsSet() throws Exception
+    {
+        final String queueName = getName();
+        final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
+
+        final Long maximumMessageCount = 100l;
+        final Long maximumMessageSize = 200l;
+        final Long maximumQueueDepth = 300l;
+        final Long maximumMessageAge = 400l;
+        final Map arguments = new HashMap();
+        arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_COUNT, maximumMessageCount);
+        arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_SIZE, maximumMessageSize);
+        arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_QUEUE_DEPTH, maximumQueueDepth);
+        arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_AGE, maximumMessageAge);
+
+        managedBroker.createNewQueue(queueName, null, true, arguments);
+
+        // Ensure the queue exists
+        assertNotNull("Queue object name expected to exist", _jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName));
+        assertNotNull("Manager queue expected to be available", _jmxUtils.getManagedQueue(queueName));
+
+        ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertEquals("Unexpected maximum message count", maximumMessageCount, managedQueue.getMaximumMessageCount());
+        assertEquals("Unexpected maximum message size", maximumMessageSize, managedQueue.getMaximumMessageSize());
+        assertEquals("Unexpected maximum queue depth", maximumQueueDepth, managedQueue.getMaximumQueueDepth());
+        assertEquals("Unexpected maximum message age", maximumMessageAge, managedQueue.getMaximumMessageAge());
+    }
+
+    /**
+     * Requires 0-10 as relies on ADDR addresses.
+     * @see AddressBasedDestinationTest for the testing of message routing to the alternate exchange
+     */
+    public void testGetSetAlternateExchange() throws Exception
+    {
+        String queueName = getTestQueueName();
+        String altExchange = "amq.fanout";
+        String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange);
+        Queue queue = _session.createQueue(addrWithAltExch);
+
+        createQueueOnBroker(queue);
+
+        final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange());
+
+        String newAltExch = "amq.topic";
+        managedQueue.setAlternateExchange(newAltExch);
+        assertEquals("Unexpected alternate exchange after set", newAltExch, managedQueue.getAlternateExchange());
+    }
+
+    /**
+     * Requires 0-10 as relies on ADDR addresses.
+     */
+    public void testRemoveAlternateExchange() throws Exception
+    {
+        String queueName = getTestQueueName();
+        String altExchange = "amq.fanout";
+        String addrWithAltExch = String.format("ADDR:%s;{create:always,node:{type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName, altExchange);
+        Queue queue = _session.createQueue(addrWithAltExch);
+
+        createQueueOnBroker(queue);
+
+        final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        assertEquals("Newly created queue does not have expected alternate exchange", altExchange, managedQueue.getAlternateExchange());
+
+        managedQueue.setAlternateExchange("");
+        assertNull("Unexpected alternate exchange after set", managedQueue.getAlternateExchange());
+    }
+
+    /**
+     * Requires persistent store
+     * Requires 0-10 as relies on ADDR addresses.
+     */
+    public void testAlternateExchangeSurvivesRestart() throws Exception
+    {
+        String nonMandatoryExchangeName = "exch" + getName();
+
+        final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST);
+        managedBroker.createNewExchange(nonMandatoryExchangeName, "fanout", true);
+
+        String queueName1 = getTestQueueName() + "1";
+        String altExchange1 = "amq.fanout";
+        String addr1WithAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue,x-declare:{alternate-exchange:'%s'}}}", queueName1, altExchange1);
+        Queue queue1 = _session.createQueue(addr1WithAltExch);
+
+        String queueName2 = getTestQueueName() + "2";
+        String addr2WithoutAltExch = String.format("ADDR:%s;{create:always,node:{durable: true,type:queue}}", queueName2);
+        Queue queue2 = _session.createQueue(addr2WithoutAltExch);
+
+        createQueueOnBroker(queue1);
+        createQueueOnBroker(queue2);
+
+        ManagedQueue managedQueue1 = _jmxUtils.getManagedQueue(queueName1);
+        assertEquals("Newly created queue1 does not have expected alternate exchange", altExchange1, managedQueue1.getAlternateExchange());
+
+        ManagedQueue managedQueue2 = _jmxUtils.getManagedQueue(queueName2);
+        assertNull("Newly created queue2 does not have expected alternate exchange", managedQueue2.getAlternateExchange());
+
+        String altExchange2 = nonMandatoryExchangeName;
+        managedQueue2.setAlternateExchange(altExchange2);
+
+        restartBroker();
+
+        managedQueue1 = _jmxUtils.getManagedQueue(queueName1);
+        assertEquals("Queue1 does not have expected alternate exchange after restart", altExchange1, managedQueue1.getAlternateExchange());
+
+        managedQueue2 = _jmxUtils.getManagedQueue(queueName2);
+        assertEquals("Queue2 does not have expected updated alternate exchange after restart", altExchange2, managedQueue2.getAlternateExchange());
+    }
+
+    /**
+     * Tests the ability to receive queue alerts as JMX notifications.
+     *
+     * @see NotificationCheckTest
+     * @see SimpleAMQQueueTest#testNotificationFiredAsync()
+     * @see SimpleAMQQueueTest#testNotificationFiredOnEnqueue()
+     */
+    public void testQueueNotification() throws Exception
+    {
+        final String queueName = getName();
+        final long maximumMessageCount = 3;
+
+        Queue queue = _session.createQueue(queueName);
+        createQueueOnBroker(queue);
+
+        ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName);
+        managedQueue.setMaximumMessageCount(maximumMessageCount);
+
+        RecordingNotificationListener listener = new RecordingNotificationListener(1);
+
+        _jmxUtils.addNotificationListener(_jmxUtils.getQueueObjectName(VIRTUAL_HOST, queueName), listener, null, null);
+
+        // Send two messages - this should *not* trigger the notification
+        sendMessage(_session, queue, 2);
+
+        assertEquals("Premature notification received", 0, listener.getNumberOfNotificationsReceived());
+
+        // A further message should trigger the message count alert
+        sendMessage(_session, queue, 1);
+
+        listener.awaitExpectedNotifications(5, TimeUnit.SECONDS);
+
+        assertEquals("Unexpected number of JMX notifications received", 1, listener.getNumberOfNotificationsReceived());
+
+        Notification notification = listener.getLastNotification();
+        assertEquals("Unexpected notification message", "MESSAGE_COUNT_ALERT 3: Maximum count on queue threshold (3) breached.", notification.getMessage());
+    }
+
+    /**
+     * Tests {@link ManagedQueue#viewMessages(long, long)} interface.
+     */
+    public void testViewSingleMessage() throws Exception
+    {
+        final List sentMessages = sendMessage(_session, _sourceQueue, 1);
+        syncSession(_session);
+        final Message sentMessage = sentMessages.get(0);
+
+        assertEquals("Unexpected queue depth", 1, _managedSourceQueue.getMessageCount().intValue());
+
+        // Check the contents of the message
+        final TabularData tab = _managedSourceQueue.viewMessages(1l, 1l);
+        assertEquals("Unexpected number of rows in table", 1, tab.size());
+        final Iterator rowItr = (Iterator) tab.values().iterator();
+
+        final CompositeData row1 = rowItr.next();
+        assertNotNull("Message should have AMQ message id", row1.get(ManagedQueue.MSG_AMQ_ID));
+        assertEquals("Unexpected queue position", 1l, row1.get(ManagedQueue.MSG_QUEUE_POS));
+        assertEquals("Unexpected redelivered flag", Boolean.FALSE, row1.get(ManagedQueue.MSG_REDELIVERED));
+
+        // Check the contents of header (encoded in a string array)
+        final String[] headerArray = (String[]) row1.get(ManagedQueue.MSG_HEADER);
+        assertNotNull("Expected message header array", headerArray);
+        final Map headers = headerArrayToMap(headerArray);
+
+        final String expectedJMSMessageID = isBroker010() ? sentMessage.getJMSMessageID().replace("ID:", "") : sentMessage.getJMSMessageID();
+        final String expectedFormattedJMSTimestamp = FastDateFormat.getInstance(ManagedQueue.JMSTIMESTAMP_DATETIME_FORMAT).format(sentMessage.getJMSTimestamp());
+        assertEquals("Unexpected JMSMessageID within header", expectedJMSMessageID, headers.get("JMSMessageID"));
+        assertEquals("Unexpected JMSPriority within header", String.valueOf(sentMessage.getJMSPriority()), headers.get("JMSPriority"));
+        assertEquals("Unexpected JMSTimestamp within header", expectedFormattedJMSTimestamp, headers.get("JMSTimestamp"));
+    }
+
+    /**
+     * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface.
+     */
+    public void testMoveMessagesBetweenQueues() throws Exception
+    {
+        final int numberOfMessagesToSend = 10;
+
+        sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+        syncSession(_session);
+        assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+        List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+        // Move first three messages to destination
+        long fromMessageId = amqMessagesIds.get(0);
+        long toMessageId = amqMessagesIds.get(2);
+        _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+        assertEquals("Unexpected queue depth on destination queue after first move", 3, _managedDestinationQueue.getMessageCount().intValue());
+        assertEquals("Unexpected queue depth on source queue after first move", 7, _managedSourceQueue.getMessageCount().intValue());
+
+        // Now move a further two messages to destination
+        fromMessageId = amqMessagesIds.get(7);
+        toMessageId = amqMessagesIds.get(8);
+        _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+        assertEquals("Unexpected queue depth on destination queue after second move", 5, _managedDestinationQueue.getMessageCount().intValue());
+        assertEquals("Unexpected queue depth on source queue after second move", 5, _managedSourceQueue.getMessageCount().intValue());
+
+        assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
+    }
+
+    /**
+     * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface.
+     */
+    public void testCopyMessagesBetweenQueues() throws Exception
+    {
+        final int numberOfMessagesToSend = 10;
+        sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+        syncSession(_session);
+        assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+        List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+        // Copy first three messages to destination
+        long fromMessageId = amqMessagesIds.get(0);
+        long toMessageId = amqMessagesIds.get(2);
+        _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+        assertEquals("Unexpected queue depth on destination queue after first copy", 3, _managedDestinationQueue.getMessageCount().intValue());
+        assertEquals("Unexpected queue depth on source queue after first copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+        // Now copy a further two messages to destination
+        fromMessageId = amqMessagesIds.get(7);
+        toMessageId = amqMessagesIds.get(8);
+        _managedSourceQueue.copyMessages(fromMessageId, toMessageId, _destinationQueueName);
+        assertEquals("Unexpected queue depth on destination queue after second copy", 5, _managedDestinationQueue.getMessageCount().intValue());
+        assertEquals("Unexpected queue depth on source queue after second copy", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+        assertMessageIndicesOn(_destinationQueue, 0, 1, 2, 7, 8);
+    }
+
+    public void testMoveMessagesBetweenQueuesWithActiveConsumerOnSourceQueue() throws Exception
+    {
+        setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
+        Connection asyncConnection = getConnection();
+        asyncConnection.start();
+
+        final int numberOfMessagesToSend = 50;
+        sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+        syncSession(_session);
+        assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+        List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+        long fromMessageId = amqMessagesIds.get(0);
+        long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
+
+        CountDownLatch consumerReadToHalfwayLatch = new CountDownLatch(numberOfMessagesToSend / 2);
+        AtomicInteger totalConsumed = new AtomicInteger(0);
+        startAsyncConsumerOn(_sourceQueue, asyncConnection, consumerReadToHalfwayLatch, totalConsumed);
+
+        boolean halfwayPointReached = consumerReadToHalfwayLatch.await(5000, TimeUnit.MILLISECONDS);
+        assertTrue("Did not read half of messages within time allowed", halfwayPointReached);
+
+        _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+        asyncConnection.stop();
+
+        // The exact number of messages moved will be non deterministic, as the number of messages processed
+        // by the consumer cannot be predicted.  There is also the possibility that a message can remain
+        // on the source queue.  This situation will arise if a message has been acquired by the consumer, but not
+        // yet delivered to the client application (i.e. MessageListener#onMessage()) when the Connection#stop() occurs.
+        //
+        // The number of messages moved + the number consumed + any messages remaining on source should
+        // *always* be equal to the number we originally sent.
+
+        int numberOfMessagesReadByConsumer = totalConsumed.intValue();
+        int numberOfMessagesOnDestinationQueue = _managedDestinationQueue.getMessageCount().intValue();
+        int numberOfMessagesRemainingOnSourceQueue = _managedSourceQueue.getMessageCount().intValue();
+
+        LOGGER.debug("Async consumer read : " + numberOfMessagesReadByConsumer
+                + " Number of messages moved to destination : " + numberOfMessagesOnDestinationQueue
+                + " Number of messages remaining on source : " + numberOfMessagesRemainingOnSourceQueue);
+        assertEquals("Unexpected number of messages after move", numberOfMessagesToSend, numberOfMessagesReadByConsumer + numberOfMessagesOnDestinationQueue + numberOfMessagesRemainingOnSourceQueue);
+    }
+
+    public void testMoveMessagesBetweenQueuesWithActiveConsumerOnDestinationQueue() throws Exception
+    {
+        setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, new Integer(1).toString());
+        Connection asyncConnection = getConnection();
+        asyncConnection.start();
+
+        final int numberOfMessagesToSend = 50;
+        sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+        syncSession(_session);
+        assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+        List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+        long fromMessageId = amqMessagesIds.get(0);
+        long toMessageId = amqMessagesIds.get(numberOfMessagesToSend - 1);
+
+        AtomicInteger totalConsumed = new AtomicInteger(0);
+        CountDownLatch allMessagesConsumedLatch = new CountDownLatch(numberOfMessagesToSend);
+        startAsyncConsumerOn(_destinationQueue, asyncConnection, allMessagesConsumedLatch, totalConsumed);
+
+        _managedSourceQueue.moveMessages(fromMessageId, toMessageId, _destinationQueueName);
+
+        allMessagesConsumedLatch.await(5000, TimeUnit.MILLISECONDS);
+        assertEquals("Did not consume all messages from destination queue", numberOfMessagesToSend, totalConsumed.intValue());
+    }
+
+    /**
+     * Tests {@link ManagedQueue#moveMessages(long, long, String)} interface.
+     */
+    public void testMoveMessageBetweenQueuesWithBrokerRestart() throws Exception
+    {
+        final int numberOfMessagesToSend = 1;
+
+        sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+        syncSession(_session);
+        assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+        restartBroker();
+
+        createManagementInterfacesForQueues();
+        createConnectionAndSession();
+
+        List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+        // Move messages to destination
+        long messageId = amqMessagesIds.get(0);
+        _managedSourceQueue.moveMessages(messageId, messageId, _destinationQueueName);
+
+        assertEquals("Unexpected queue depth on destination queue after move", 1, _managedDestinationQueue.getMessageCount().intValue());
+        assertEquals("Unexpected queue depth on source queue after move", 0, _managedSourceQueue.getMessageCount().intValue());
+
+        assertMessageIndicesOn(_destinationQueue, 0);
+    }
+
+    /**
+     * Tests {@link ManagedQueue#copyMessages(long, long, String)} interface.
+     */
+    public void testCopyMessageBetweenQueuesWithBrokerRestart() throws Exception
+    {
+        final int numberOfMessagesToSend = 1;
+
+        sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+        syncSession(_session);
+        assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+
+        restartBroker();
+
+        createManagementInterfacesForQueues();
+        createConnectionAndSession();
+
+        List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+
+        // Move messages to destination
+        long messageId = amqMessagesIds.get(0);
+        _managedSourceQueue.copyMessages(messageId, messageId, _destinationQueueName);
+
+        assertEquals("Unexpected queue depth on destination queue after copy", 1, _managedDestinationQueue.getMessageCount().intValue());
+        assertEquals("Unexpected queue depth on source queue after copy", 1, _managedSourceQueue.getMessageCount().intValue());
+
+        assertMessageIndicesOn(_destinationQueue, 0);
+    }
+
+    /**
+     * Tests {@link ManagedQueue#deleteMessages(long, long)} interface.
+     */
+    public void testDeleteMessages() throws Exception
+    {
+        final int numberOfMessagesToSend = 15;
+
+        sendMessage(_session, _sourceQueue, numberOfMessagesToSend);
+        syncSession(_session);
+        assertEquals("Unexpected queue depth after send", numberOfMessagesToSend, _managedSourceQueue.getMessageCount().intValue());
+        List amqMessagesIds = getAMQMessageIdsOn(_managedSourceQueue, 1, numberOfMessagesToSend);
+        // Current expected queue state, in terms of message header indices: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
+
+        // Delete the first message (Remember the amqMessagesIds list, and the message indices added as a property when sending, are both 0-based index)
+        long fromMessageId = amqMessagesIds.get(0);
+        long toMessageId = fromMessageId;
+        _managedSourceQueue.deleteMessages(fromMessageId, toMessageId);
+        assertEquals("Unexpected message count after first deletion", numberOfMessagesToSend - 1, _managedSourceQueue.getMessageCount().intValue());
+        // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
+
+        // Delete the 9th-10th messages, in the middle of the queue
+        fromMessageId = amqMessagesIds.get(8);
+        toMessageId = amqMessagesIds.get(9);
+        _managedSourceQueue.deleteMessages(fromMessageId, toMessageId);
+        assertEquals("Unexpected message count after third deletion", numberOfMessagesToSend - 3, _managedSourceQueue.getMessageCount().intValue());
+        // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,7,X,X,10,11,12,13,14]
+
+        // Delete the 11th and 12th messages, but still include the IDs for the 9th and 10th messages in the
+        // range to ensure their IDs are 'skipped' until the matching messages are found
+        fromMessageId = amqMessagesIds.get(8);
+        toMessageId = amqMessagesIds.get(11);
+        _managedSourceQueue.deleteMessages(fromMessageId, toMessageId);
+        assertEquals("Unexpected message count after fourth deletion", numberOfMessagesToSend - 5, _managedSourceQueue.getMessageCount().intValue());
+        // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,7,X,X,X,X,12,13,14]
+
+        // Delete the 8th message and the 13th message, including the IDs for the 9th-12th messages in the
+        // range to ensure their IDs are 'skipped' and the other matching message is found
+        fromMessageId = amqMessagesIds.get(7);
+        toMessageId = amqMessagesIds.get(12);
+        _managedSourceQueue.deleteMessages(fromMessageId, toMessageId);
+        assertEquals("Unexpected message count after fourth deletion", numberOfMessagesToSend - 7, _managedSourceQueue.getMessageCount().intValue());
+        // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,X,X,X,X,X,X,13,14]
+
+        // Delete the last message message
+        fromMessageId = amqMessagesIds.get(numberOfMessagesToSend -1);
+        toMessageId = fromMessageId;
+        _managedSourceQueue.deleteMessages(fromMessageId, toMessageId);
+        assertEquals("Unexpected message count after second deletion", numberOfMessagesToSend - 8, _managedSourceQueue.getMessageCount().intValue());
+        // Current expected queue state, in terms of message header indices: [X,1,2,3,4,5,6,X,X,X,X,X,X,13,X]
+
+        // Verify the message indices with a consumer
+        assertMessageIndicesOn(_sourceQueue, 1,2,3,4,5,6,13);
+    }
+
+    @Override
+    public Message createNextMessage(Session session, int messageNumber) throws JMSException
+    {
+        Message message = session.createTextMessage(getContentForMessageNumber(messageNumber));
+        message.setIntProperty(INDEX, messageNumber);
+        return message;
+    }
+
+    private void startAsyncConsumerOn(Destination queue, Connection asyncConnection,
+            final CountDownLatch requiredNumberOfMessagesRead, final AtomicInteger totalConsumed) throws Exception
+    {
+        Session session = asyncConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+        MessageConsumer consumer = session.createConsumer(queue);
+        consumer.setMessageListener(new MessageListener()
+        {
+
+            @Override
+            public void onMessage(Message arg0)
+            {
+                totalConsumed.incrementAndGet();
+                requiredNumberOfMessagesRead.countDown();
+            }
+        });
+    }
+
+    private void assertMessageIndicesOn(Destination queue, int... expectedIndices) throws Exception
+    {
+        MessageConsumer consumer = _session.createConsumer(queue);
+
+        for (int i : expectedIndices)
+        {
+            TextMessage message = (TextMessage)consumer.receive(1000);
+            assertNotNull("Expected message with index " + i, message);
+            assertEquals("Expected message with index " + i, i, message.getIntProperty(INDEX));
+            assertEquals("Expected message content", getContentForMessageNumber(i), message.getText());
+        }
+
+        assertNull("Unexpected message encountered", consumer.receive(1000));
+    }
+
+    private List getAMQMessageIdsOn(ManagedQueue managedQueue, long startIndex, long endIndex) throws Exception
+    {
+        final SortedSet messageIds = new TreeSet();
+
+        final TabularData tab = managedQueue.viewMessages(startIndex, endIndex);
+        final Iterator rowItr = (Iterator) tab.values().iterator();
+        while(rowItr.hasNext())
+        {
+            final CompositeData row = rowItr.next();
+            long amqMessageId = (Long)row.get(ManagedQueue.MSG_AMQ_ID);
+            messageIds.add(amqMessageId);
+        }
+
+        return new ArrayList(messageIds);
+    }
+
+    /**
+     *
+     * Utility method to convert array of Strings in the form x = y into a
+     * map with key/value x => y.
+     *
+     */
+    private Map headerArrayToMap(final String[] headerArray)
+    {
+        final Map headerMap = new HashMap();
+        final List headerList = Arrays.asList(headerArray);
+        for (Iterator iterator = headerList.iterator(); iterator.hasNext();)
+        {
+            final String nameValuePair = iterator.next();
+            final String[] nameValue = nameValuePair.split(" *= *", 2);
+            headerMap.put(nameValue[0], nameValue[1]);
+        }
+        return headerMap;
+    }
+
+    private void createQueueOnBroker(Destination destination) throws JMSException
+    {
+        _session.createConsumer(destination).close(); // Create a consumer only to cause queue creation
+    }
+
+    private void syncSession(Session session) throws Exception
+    {
+        ((AMQSession)session).sync();
+    }
+
+    private void createConnectionAndSession() throws JMSException,
+            NamingException
+    {
+        _connection = getConnection();
+        _connection.start();
+        _session = _connection.createSession(true, Session.SESSION_TRANSACTED);
+    }
+
+    private void createManagementInterfacesForQueues()
+    {
+        _managedSourceQueue = _jmxUtils.getManagedQueue(_sourceQueueName);
+        _managedDestinationQueue = _jmxUtils.getManagedQueue(_destinationQueueName);
+    }
+
+    private String getContentForMessageNumber(int msgCount)
+    {
+        return "Message count " + msgCount;
+    }
+
+    private final class RecordingNotificationListener implements NotificationListener
+    {
+        private final CountDownLatch _notificationReceivedLatch;
+        private final AtomicInteger _numberOfNotifications;
+        private final AtomicReference _lastNotification;
+
+        private RecordingNotificationListener(int expectedNumberOfNotifications)
+        {
+            _notificationReceivedLatch = new CountDownLatch(expectedNumberOfNotifications);
+            _numberOfNotifications = new AtomicInteger(0);
+            _lastNotification = new AtomicReference();
+        }
+
+        @Override
+        public void handleNotification(Notification notification, Object handback)
+        {
+            _lastNotification.set(notification);
+            _numberOfNotifications.incrementAndGet();
+            _notificationReceivedLatch.countDown();
+        }
+
+        public int getNumberOfNotificationsReceived()
+        {
+            return _numberOfNotifications.get();
+        }
+
+        public Notification getLastNotification()
+        {
+            return _lastNotification.get();
+        }
+
+        public void awaitExpectedNotifications(long timeout, TimeUnit timeunit) throws InterruptedException
+        {
+            _notificationReceivedLatch.await(timeout, timeunit);
+        }
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
new file mode 100644
index 0000000000..72fbd65acc
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import java.util.List;
+
+import javax.jms.Connection;
+import javax.jms.MessageConsumer;
+import javax.jms.Queue;
+import javax.jms.Session;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.management.common.mbeans.ServerInformation;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+public class StatisticsTest extends QpidBrokerTestCase
+{
+    private static final String TEST_VIRTUALHOST1 = "test1";
+    private static final String TEST_VIRTUALHOST2 = "test2";
+
+    private static final String TEST_USER = "admin";
+    private static final String TEST_PASSWORD = "admin";
+    private static final int MESSAGE_COUNT_TEST = 5;
+    private static final int MESSAGE_COUNT_DEV = 9;
+
+    private JMXTestUtils _jmxUtils;
+    private Connection _vhost1Connection, _vhost2Connection;
+    private Session _vhost1Session, _vhost2Session;
+    private Queue _vhost1Queue, _vhost2Queue;
+    protected String _brokerUrl;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        createTestVirtualHost(0, TEST_VIRTUALHOST1);
+        createTestVirtualHost(0, TEST_VIRTUALHOST2);
+
+        _jmxUtils = new JMXTestUtils(this, TEST_USER, TEST_PASSWORD);
+        _jmxUtils.setUp();
+
+        super.setUp();
+
+        _brokerUrl = getBroker().toString();
+        _vhost1Connection = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", TEST_VIRTUALHOST1);
+        _vhost2Connection = new AMQConnection(_brokerUrl, TEST_USER, TEST_PASSWORD, "clientid", TEST_VIRTUALHOST2);
+        _vhost1Connection.start();
+        _vhost2Connection.start();
+
+        _vhost1Session = _vhost1Connection.createSession(true, Session.SESSION_TRANSACTED);
+        _vhost2Session = _vhost2Connection.createSession(true, Session.SESSION_TRANSACTED);
+
+        _vhost1Queue = _vhost2Session.createQueue(getTestQueueName());
+        _vhost2Queue = _vhost1Session.createQueue(getTestQueueName());
+
+        //Create queues by opening and closing consumers
+        final MessageConsumer vhost1Consumer = _vhost1Session.createConsumer(_vhost2Queue);
+        vhost1Consumer.close();
+        final MessageConsumer vhost2Consumer = _vhost2Session.createConsumer(_vhost1Queue);
+        vhost2Consumer.close();
+
+        _jmxUtils.open();
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        _jmxUtils.close();
+
+        super.tearDown();
+    }
+
+    public void testInitialStatisticValues() throws Exception
+    {
+        //Check initial values
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, 0, 0, 0, 0);
+        checkVHostStatistics(TEST_VIRTUALHOST1, 0, 0, 0, 0);
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0);
+        checkVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0);
+        checkBrokerStatistics(0, 0, 0, 0);
+    }
+
+    public void testSendOnSingleVHost() throws Exception
+    {
+        sendMessagesAndSync(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST);
+
+        //Check values
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+        checkVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0);
+        checkVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0);
+        checkBrokerStatistics(MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+    }
+
+    public void testSendOnTwoVHosts() throws Exception
+    {
+        sendMessagesAndSync(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST);
+        sendMessagesAndSync(_vhost2Session, _vhost1Queue, MESSAGE_COUNT_DEV);
+
+        //Check values
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+        checkVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, 0, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, 0);
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2,  MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0);
+        checkVHostStatistics(TEST_VIRTUALHOST2,  MESSAGE_COUNT_DEV, 0, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, 0);
+        checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, 0, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, 0);
+    }
+
+    public void testSendAndConsumeOnSingleVHost() throws Exception
+    {
+        sendMessagesAndSync(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST);
+        consumeMessages(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST);
+
+        //Check values
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+        checkVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0);
+        checkVHostStatistics(TEST_VIRTUALHOST2, 0, 0, 0, 0);
+        checkBrokerStatistics(MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+    }
+
+    public void testSendAndConsumeOnTwoVHosts() throws Exception
+    {
+        sendMessagesAndSync(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST);
+        sendMessagesAndSync(_vhost2Session, _vhost1Queue, MESSAGE_COUNT_DEV);
+        consumeMessages(_vhost1Session, _vhost2Queue, MESSAGE_COUNT_TEST);
+        consumeMessages(_vhost2Session, _vhost1Queue, MESSAGE_COUNT_DEV);
+
+        //Check values
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+        checkVHostStatistics(TEST_VIRTUALHOST1, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_TEST * DEFAULT_MESSAGE_SIZE);
+        checkSingleConnectionOnVHostStatistics(TEST_VIRTUALHOST2,  MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE);
+        checkVHostStatistics(TEST_VIRTUALHOST2,  MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE, MESSAGE_COUNT_DEV * DEFAULT_MESSAGE_SIZE);
+        checkBrokerStatistics(MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE, (MESSAGE_COUNT_TEST + MESSAGE_COUNT_DEV) * DEFAULT_MESSAGE_SIZE);
+    }
+
+    private void sendMessagesAndSync(Session session, Queue queue, int numberOfMessages) throws Exception
+    {
+        //Send messages via connection on and sync
+        sendMessage(session, queue, numberOfMessages);
+        ((AMQSession)session).sync();
+    }
+
+    private void consumeMessages(Session session, Queue queue, int numberOfMessages) throws Exception
+    {
+        //consume the messages on the virtual host
+        final MessageConsumer consumer = session.createConsumer(queue);
+        for (int i = 0 ; i < numberOfMessages ; i++)
+        {
+            assertNotNull("an expected message was not received", consumer.receive(1500));
+        }
+        session.commit();
+        consumer.close();
+    }
+
+    private void checkSingleConnectionOnVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived)
+    {
+        List managedConnections = _jmxUtils.getManagedConnections(vHostName);
+        assertEquals(1, managedConnections.size());
+
+        ManagedConnection managedConnection = managedConnections.get(0);
+
+        assertEquals(messagesSent, managedConnection.getTotalMessagesReceived());
+        assertEquals(messagesReceived, managedConnection.getTotalMessagesDelivered());
+
+        assertEquals(dataSent, managedConnection.getTotalDataReceived());
+        assertEquals(dataReceived, managedConnection.getTotalDataDelivered());
+    }
+
+    private void checkVHostStatistics(String vHostName, long messagesSent, long messagesReceived, long dataSent, long dataReceived)
+    {
+        ManagedBroker vhost = _jmxUtils.getManagedBroker(vHostName);
+
+        assertEquals(messagesSent, vhost.getTotalMessagesReceived());
+        assertEquals(messagesReceived, vhost.getTotalMessagesDelivered());
+
+        assertEquals(dataSent, vhost.getTotalDataReceived());
+        assertEquals(dataReceived, vhost.getTotalDataDelivered());
+    }
+
+    private void checkBrokerStatistics(long messagesSent, long messagesReceived, long dataSent, long dataReceived)
+    {
+        ServerInformation broker = _jmxUtils.getServerInformation();
+
+        assertEquals(messagesSent, broker.getTotalMessagesReceived());
+        assertEquals(messagesReceived, broker.getTotalMessagesDelivered());
+
+        assertEquals(dataSent, broker.getTotalDataReceived());
+        assertEquals(dataReceived, broker.getTotalDataDelivered());
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java
new file mode 100644
index 0000000000..7eff1c89ee
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementTest.java
@@ -0,0 +1,260 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jms.Connection;
+import javax.jms.JMSException;
+
+import org.apache.qpid.management.common.mbeans.UserManagement;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
+import org.apache.qpid.server.security.auth.manager.AbstractPrincipalDatabaseAuthManagerFactory;
+import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory;
+import org.apache.qpid.test.utils.JMXTestUtils;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.apache.qpid.tools.security.Passwd;
+
+/**
+ * System test for User Management.
+ *
+ */
+public class UserManagementTest extends QpidBrokerTestCase
+{
+    private static final String TEST_NEWPASSWORD = "newpassword";
+    private static final String TEST_PASSWORD = "password";
+    private JMXTestUtils _jmxUtils;
+    private String _testUserName;
+    private File _passwordFile;
+    private UserManagement _userManagement;
+    private Passwd _passwd;
+
+    public void setUp() throws Exception
+    {
+        _passwd = createPasswordEncodingUtility();
+        _passwordFile = createTemporaryPasswordFileWithJmxAdminUser();
+
+        Map newAttributes = new HashMap();
+        newAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, getAuthenticationManagerType());
+        newAttributes.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, _passwordFile.getAbsolutePath());
+        getBrokerConfiguration().setObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, newAttributes);
+
+        _jmxUtils = new JMXTestUtils(this);
+        _jmxUtils.setUp();
+
+        super.setUp();
+        _jmxUtils.open();
+
+        _testUserName = getTestName() + System.currentTimeMillis();
+
+        _userManagement = _jmxUtils.getUserManagement();
+    }
+
+
+    public void tearDown() throws Exception
+    {
+        try
+        {
+            if (_jmxUtils != null)
+            {
+                _jmxUtils.close();
+            }
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    public void testCreateUser() throws Exception
+    {
+        final int initialNumberOfUsers = _userManagement.viewUsers().size();
+        assertFileDoesNotContainsPasswordForUser(_testUserName);
+
+        boolean success = _userManagement.createUser(_testUserName, TEST_PASSWORD);
+        assertTrue("Should have been able to create new user " + _testUserName, success);
+        assertEquals("Unexpected number of users after add", initialNumberOfUsers + 1, _userManagement.viewUsers().size());
+
+        assertFileContainsPasswordForUser(_testUserName);
+    }
+
+    public void testJmsLoginForNewUser() throws Exception
+    {
+        assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
+        testCreateUser();
+
+        assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD);
+    }
+
+    public void testDeleteUser() throws Exception
+    {
+        final int initialNumberOfUsers = _userManagement.viewUsers().size();
+
+        testCreateUser();
+
+        boolean success = _userManagement.deleteUser(_testUserName);
+        assertTrue("Should have been able to delete new user " + _testUserName, success);
+        assertEquals("Unexpected number of users after delete", initialNumberOfUsers, _userManagement.viewUsers().size());
+        assertFileDoesNotContainsPasswordForUser(_testUserName);
+    }
+
+    public void testJmsLoginNotPossibleForDeletedUser() throws Exception
+    {
+        testDeleteUser();
+
+        assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
+    }
+
+    public void testSetPassword() throws Exception
+    {
+        testCreateUser();
+
+        _userManagement.setPassword(_testUserName, TEST_NEWPASSWORD);
+
+        assertFileContainsPasswordForUser(_testUserName);
+    }
+
+    public void testJmsLoginForPasswordChangedUser() throws Exception
+    {
+        testSetPassword();
+
+        assertJmsConnectionSucceeds(_testUserName, TEST_NEWPASSWORD);
+        assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
+    }
+
+    public void testReload() throws Exception
+    {
+        writePasswordFile(_passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD, _testUserName, TEST_PASSWORD);
+
+        assertJmsConnectionFails(_testUserName, TEST_PASSWORD);
+
+        _userManagement.reloadData();
+
+        assertJmsConnectionSucceeds(_testUserName, TEST_PASSWORD);
+    }
+
+    protected Passwd createPasswordEncodingUtility()
+    {
+        return new Passwd()
+        {
+            @Override
+            public String getOutput(String username, String password)
+            {
+                return username + ":" + password;
+            }
+        };
+    }
+
+    protected String getAuthenticationManagerType()
+    {
+        return PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE;
+    }
+
+    private File createTemporaryPasswordFileWithJmxAdminUser() throws Exception
+    {
+        File passwordFile = File.createTempFile("passwd", "pwd");
+        passwordFile.deleteOnExit();
+        writePasswordFile(passwordFile, JMXTestUtils.DEFAULT_USERID, JMXTestUtils.DEFAULT_PASSWORD);
+        return passwordFile;
+    }
+
+    private void writePasswordFile(File passwordFile, String... userNamePasswordPairs) throws Exception
+    {
+        FileWriter writer = null;
+        try
+        {
+            writer = new FileWriter(passwordFile);
+            for (int i = 0; i < userNamePasswordPairs.length; i=i+2)
+            {
+                String username = userNamePasswordPairs[i];
+                String password = userNamePasswordPairs[i+1];
+                writer.append(_passwd.getOutput(username, password) + "\n");
+            }
+        }
+        finally
+        {
+            writer.close();
+        }
+    }
+
+
+    private void assertFileContainsPasswordForUser(String username) throws IOException
+    {
+        assertTrue("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username));
+    }
+
+    private void assertFileDoesNotContainsPasswordForUser(String username) throws IOException
+    {
+        assertFalse("Could not find password for user " + username + " within " + _passwordFile, passwordFileContainsUser(username));
+    }
+
+    private boolean passwordFileContainsUser(String username) throws IOException
+    {
+        BufferedReader reader = null;
+        try
+        {
+            reader = new BufferedReader(new FileReader(_passwordFile));
+            String line = reader.readLine();
+            while(line != null)
+            {
+                if (line.startsWith(username))
+                {
+                    return true;
+                }
+                line = reader.readLine();
+            }
+
+            return false;
+        }
+        finally
+        {
+            reader.close();
+        }
+    }
+
+    private void assertJmsConnectionSucceeds(String username, String password) throws Exception
+    {
+        Connection connection = getConnection(username, password);
+        assertNotNull(connection);
+    }
+
+    private void assertJmsConnectionFails(String username, String password) throws Exception
+    {
+        try
+        {
+            getConnection(username, password);
+            fail("Exception not thrown");
+        }
+        catch (JMSException e)
+        {
+            // PASS
+        }
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java
new file mode 100644
index 0000000000..1423bc557e
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/UserManagementWithBase64MD5PasswordsTest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.management.jmx;
+
+import org.apache.qpid.server.security.auth.manager.Base64MD5PasswordFileAuthenticationManagerFactory;
+import org.apache.qpid.tools.security.Passwd;
+
+public class UserManagementWithBase64MD5PasswordsTest extends UserManagementTest
+{
+    @Override
+    protected Passwd createPasswordEncodingUtility()
+    {
+        return new Passwd();
+    }
+
+    @Override
+    protected String getAuthenticationManagerType()
+    {
+        return Base64MD5PasswordFileAuthenticationManagerFactory.PROVIDER_TYPE;
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
new file mode 100644
index 0000000000..16253139ce
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java
@@ -0,0 +1,270 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+
+import javax.jms.JMSException;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+
+public class Asserts
+{
+    public static final String STATISTICS_ATTRIBUTE = "statistics";
+
+    public static void assertVirtualHost(String virtualHostName, Map virtualHost)
+    {
+        assertNotNull("Virtualhost " + virtualHostName + " data are not found", virtualHost);
+        assertAttributesPresent(virtualHost, VirtualHost.AVAILABLE_ATTRIBUTES, VirtualHost.TIME_TO_LIVE,
+                VirtualHost.CREATED, VirtualHost.UPDATED, VirtualHost.SUPPORTED_QUEUE_TYPES, VirtualHost.STORE_PATH, VirtualHost.CONFIG_PATH);
+
+        assertEquals("Unexpected value of attribute " + VirtualHost.NAME, virtualHostName, virtualHost.get(VirtualHost.NAME));
+        assertNotNull("Unexpected value of attribute " + VirtualHost.ID, virtualHost.get(VirtualHost.ID));
+        assertEquals("Unexpected value of attribute " + VirtualHost.STATE, State.ACTIVE.name(),
+                virtualHost.get(VirtualHost.STATE));
+        assertEquals("Unexpected value of attribute " + VirtualHost.DURABLE, Boolean.TRUE,
+                virtualHost.get(VirtualHost.DURABLE));
+        assertEquals("Unexpected value of attribute " + VirtualHost.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+                virtualHost.get(VirtualHost.LIFETIME_POLICY));
+        assertEquals("Unexpected value of attribute " + VirtualHost.DEAD_LETTER_QUEUE_ENABLED, Boolean.FALSE,
+                virtualHost.get(VirtualHost.DEAD_LETTER_QUEUE_ENABLED));
+
+        @SuppressWarnings("unchecked")
+        Collection exchangeTypes = (Collection) virtualHost.get(VirtualHost.SUPPORTED_EXCHANGE_TYPES);
+        assertEquals("Unexpected value of attribute " + VirtualHost.SUPPORTED_EXCHANGE_TYPES,
+                new HashSet(Arrays.asList("headers", "topic", "direct", "fanout")),
+                new HashSet(exchangeTypes));
+
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) virtualHost.get(STATISTICS_ATTRIBUTE);
+        Asserts.assertAttributesPresent(statistics, VirtualHost.AVAILABLE_STATISTICS, VirtualHost.BYTES_RETAINED,
+                VirtualHost.LOCAL_TRANSACTION_BEGINS, VirtualHost.LOCAL_TRANSACTION_ROLLBACKS,
+                VirtualHost.MESSAGES_RETAINED, VirtualHost.STATE_CHANGED, VirtualHost.XA_TRANSACTION_BRANCH_ENDS,
+                VirtualHost.XA_TRANSACTION_BRANCH_STARTS, VirtualHost.XA_TRANSACTION_BRANCH_SUSPENDS);
+
+    }
+
+    public static void assertQueue(String queueName, String queueType, Map queueData)
+    {
+        assertQueue(queueName, queueType, queueData, null);
+    }
+
+    public static void assertQueue(String queueName, String queueType, Map queueData, Map expectedAttributes)
+    {
+        assertNotNull("Queue " + queueName + " is not found!", queueData);
+        Asserts.assertAttributesPresent(queueData, Queue.AVAILABLE_ATTRIBUTES, Queue.CREATED, Queue.UPDATED,
+                Queue.DESCRIPTION, Queue.TIME_TO_LIVE, Queue.ALTERNATE_EXCHANGE, Queue.OWNER, Queue.NO_LOCAL, Queue.LVQ_KEY,
+                Queue.SORT_KEY, Queue.MESSAGE_GROUP_KEY, Queue.MESSAGE_GROUP_DEFAULT_GROUP,
+                Queue.MESSAGE_GROUP_SHARED_GROUPS, Queue.PRIORITIES);
+
+        assertEquals("Unexpected value of queue attribute " + Queue.NAME, queueName, queueData.get(Queue.NAME));
+        assertNotNull("Unexpected value of queue attribute " + Queue.ID, queueData.get(Queue.ID));
+        assertEquals("Unexpected value of queue attribute " + Queue.STATE, State.ACTIVE.name(), queueData.get(Queue.STATE));
+        assertEquals("Unexpected value of queue attribute " + Queue.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+                queueData.get(Queue.LIFETIME_POLICY));
+        assertEquals("Unexpected value of queue attribute " + Queue.TYPE, queueType, queueData.get(Queue.TYPE));
+        if (expectedAttributes == null)
+        {
+            assertEquals("Unexpected value of queue attribute " + Queue.EXCLUSIVE, Boolean.FALSE, queueData.get(Queue.EXCLUSIVE));
+            assertEquals("Unexpected value of queue attribute " + Queue.MAXIMUM_DELIVERY_ATTEMPTS, 0,
+                    queueData.get(Queue.MAXIMUM_DELIVERY_ATTEMPTS));
+            assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 0,
+                    queueData.get(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES));
+            assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 0,
+                    queueData.get(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES));
+            assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_FLOW_STOPPED, Boolean.FALSE,
+                    queueData.get(Queue.QUEUE_FLOW_STOPPED));
+        }
+        else
+        {
+            for (Map.Entry attribute : expectedAttributes.entrySet())
+            {
+                assertEquals("Unexpected value of " + queueName + " queue attribute " + attribute.getKey(),
+                        attribute.getValue(), queueData.get(attribute.getKey()));
+            }
+        }
+
+        assertNotNull("Unexpected value of queue attribute statistics", queueData.get(Asserts.STATISTICS_ATTRIBUTE));
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) queueData.get(Asserts.STATISTICS_ATTRIBUTE);
+        Asserts.assertAttributesPresent(statistics, Queue.AVAILABLE_STATISTICS, Queue.DISCARDS_TTL_BYTES,
+                Queue.DISCARDS_TTL_MESSAGES, Queue.STATE_CHANGED);
+    }
+
+    public static void assertAttributesPresent(Map data, String[] attributes)
+    {
+        for (String name : attributes)
+        {
+            assertNotNull("Attribute " + name + " is not present", data.get(name));
+        }
+    }
+
+    public static void assertAttributesPresent(Map data, Collection attributes,
+            String... unsupportedAttributes)
+    {
+        for (String name : attributes)
+        {
+            boolean unsupported = false;
+            for (String unsupportedAttribute : unsupportedAttributes)
+            {
+                if (unsupportedAttribute.equals(name))
+                {
+                    unsupported = true;
+                    break;
+                }
+            }
+            if (unsupported)
+            {
+                continue;
+            }
+            assertNotNull("Attribute " + name + " is not present", data.get(name));
+        }
+    }
+
+    public static void assertConnection(Map connectionData, AMQConnection connection) throws JMSException
+    {
+        assertNotNull("Unexpected connection data", connectionData);
+        assertAttributesPresent(connectionData, Connection.AVAILABLE_ATTRIBUTES, Connection.STATE, Connection.DURABLE,
+                Connection.LIFETIME_POLICY, Connection.TIME_TO_LIVE, Connection.CREATED, Connection.UPDATED,
+                Connection.INCOMING, Connection.REMOTE_PROCESS_NAME, Connection.REMOTE_PROCESS_PID,
+                Connection.LOCAL_ADDRESS, Connection.PROPERTIES);
+
+        assertEquals("Unexpected value of connection attribute " + Connection.SESSION_COUNT_LIMIT,
+                (int) connection.getMaximumChannelCount(), connectionData.get(Connection.SESSION_COUNT_LIMIT));
+        assertEquals("Unexpected value of connection attribute " + Connection.CLIENT_ID, "clientid",
+                connectionData.get(Connection.CLIENT_ID));
+        assertEquals("Unexpected value of connection attribute " + Connection.PRINCIPAL, "guest",
+                connectionData.get(Connection.PRINCIPAL));
+
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) connectionData.get(STATISTICS_ATTRIBUTE);
+        assertAttributesPresent(statistics, Connection.AVAILABLE_STATISTICS, Connection.LOCAL_TRANSACTION_BEGINS,
+                Connection.LOCAL_TRANSACTION_ROLLBACKS, Connection.STATE_CHANGED, Connection.XA_TRANSACTION_BRANCH_ENDS,
+                Connection.XA_TRANSACTION_BRANCH_STARTS, Connection.XA_TRANSACTION_BRANCH_SUSPENDS);
+        assertEquals("Unexpected value of connection statistics attribute " + Connection.SESSION_COUNT, 1,
+                statistics.get(Connection.SESSION_COUNT));
+    }
+
+    public static void assertPortAttributes(Map port)
+    {
+
+        assertNotNull("Unexpected value of attribute " + Port.ID, port.get(Port.ID));
+        assertEquals("Unexpected value of attribute " + Port.DURABLE, Boolean.FALSE, port.get(Port.DURABLE));
+        assertEquals("Unexpected value of attribute " + Port.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+                port.get(Broker.LIFETIME_POLICY));
+        assertEquals("Unexpected value of attribute " + Port.STATE, State.ACTIVE.name(), port.get(Port.STATE));
+        assertEquals("Unexpected value of attribute " + Port.TIME_TO_LIVE, 0, port.get(Port.TIME_TO_LIVE));
+
+        @SuppressWarnings("unchecked")
+        Collection protocols = (Collection) port.get(Port.PROTOCOLS);
+        assertNotNull("Unexpected value of attribute " + Port.PROTOCOLS, protocols);
+        boolean isAMQPPort = false;
+        for (String protocolName : protocols)
+        {
+            if (Protocol.valueOf(protocolName).isAMQP())
+            {
+                isAMQPPort = true;
+                break;
+            }
+        }
+        if (isAMQPPort)
+        {
+            assertAttributesPresent(port, Port.AVAILABLE_ATTRIBUTES, Port.CREATED, Port.UPDATED, Port.AUTHENTICATION_MANAGER);
+            assertNotNull("Unexpected value of attribute " + Port.BINDING_ADDRESS, port.get(Port.BINDING_ADDRESS));
+        }
+        else
+        {
+            assertAttributesPresent(port, Port.AVAILABLE_ATTRIBUTES, Port.CREATED, Port.UPDATED, Port.AUTHENTICATION_MANAGER,
+                    Port.BINDING_ADDRESS, Port.TCP_NO_DELAY, Port.SEND_BUFFER_SIZE, Port.RECEIVE_BUFFER_SIZE,
+                    Port.NEED_CLIENT_AUTH, Port.WANT_CLIENT_AUTH);
+        }
+
+        @SuppressWarnings("unchecked")
+        Collection transports = (Collection) port.get(Port.TRANSPORTS);
+        assertEquals("Unexpected value of attribute " + Port.TRANSPORTS, new HashSet(Arrays.asList("TCP")),
+                new HashSet(transports));
+    }
+
+    public static void assertDurableExchange(String exchangeName, String type, Map exchangeData)
+    {
+        assertExchange(exchangeName, type, exchangeData);
+
+        assertEquals("Unexpected value of exchange attribute " + Exchange.DURABLE, Boolean.TRUE,
+                exchangeData.get(Exchange.DURABLE));
+    }
+
+    public static void assertExchange(String exchangeName, String type, Map exchangeData)
+    {
+        assertNotNull("Exchange " + exchangeName + " is not found!", exchangeData);
+        assertAttributesPresent(exchangeData, Exchange.AVAILABLE_ATTRIBUTES, Exchange.CREATED, Exchange.UPDATED,
+                Exchange.ALTERNATE_EXCHANGE, Exchange.TIME_TO_LIVE);
+
+        assertEquals("Unexpected value of exchange attribute " + Exchange.NAME, exchangeName,
+                exchangeData.get(Exchange.NAME));
+        assertNotNull("Unexpected value of exchange attribute " + Exchange.ID, exchangeData.get(VirtualHost.ID));
+        assertEquals("Unexpected value of exchange attribute " + Exchange.STATE, State.ACTIVE.name(),
+                exchangeData.get(Exchange.STATE));
+
+        assertEquals("Unexpected value of exchange attribute " + Exchange.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+                exchangeData.get(Exchange.LIFETIME_POLICY));
+        assertEquals("Unexpected value of exchange attribute " + Exchange.TYPE, type, exchangeData.get(Exchange.TYPE));
+        assertNotNull("Unexpected value of exchange attribute statistics", exchangeData.get(STATISTICS_ATTRIBUTE));
+
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) exchangeData.get(STATISTICS_ATTRIBUTE);
+        assertAttributesPresent(statistics, Exchange.AVAILABLE_STATISTICS, Exchange.STATE_CHANGED, Exchange.PRODUCER_COUNT);
+    }
+
+    public static void assertBinding(String bindingName, String queueName, String exchange, Map binding)
+    {
+        assertNotNull("Binding map should not be null", binding);
+        assertAttributesPresent(binding, Binding.AVAILABLE_ATTRIBUTES, Binding.STATE, Binding.TIME_TO_LIVE,
+                Binding.CREATED, Binding.UPDATED);
+
+        assertEquals("Unexpected binding attribute " + Binding.NAME, bindingName, binding.get(Binding.NAME));
+        assertEquals("Unexpected binding attribute " + Binding.QUEUE, queueName, binding.get(Binding.QUEUE));
+        assertEquals("Unexpected binding attribute " + Binding.EXCHANGE, exchange, binding.get(Binding.EXCHANGE));
+        assertEquals("Unexpected binding attribute " + Binding.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+                binding.get(Binding.LIFETIME_POLICY));
+    }
+
+    public static void assertBinding(String queueName, String exchange, Map binding)
+    {
+        assertBinding(queueName, queueName, exchange, binding);
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java
new file mode 100644
index 0000000000..a171b4459b
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.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.systest.rest;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.User;
+
+public class AuthenticationProviderRestTest extends QpidRestTestCase
+{
+
+    public void testGet() throws Exception
+    {
+        List> providerDetails = getRestTestHelper().getJsonAsList("/rest/authenticationprovider");
+        assertNotNull("Providers details cannot be null", providerDetails);
+        assertEquals("Unexpected number of providers", 1, providerDetails.size());
+        for (Map provider : providerDetails)
+        {
+            assertProvider("PrincipalDatabaseAuthenticationManager", provider);
+            Map data = getRestTestHelper().getJsonAsSingletonList("/rest/authenticationprovider/"
+                    + provider.get(AuthenticationProvider.NAME));
+            assertNotNull("Cannot load data for " + provider.get(AuthenticationProvider.NAME), data);
+            assertProvider("PrincipalDatabaseAuthenticationManager", data);
+        }
+    }
+
+    private void assertProvider(String type, Map provider)
+    {
+        Asserts.assertAttributesPresent(provider, AuthenticationProvider.AVAILABLE_ATTRIBUTES,
+                AuthenticationProvider.CREATED, AuthenticationProvider.UPDATED, AuthenticationProvider.DESCRIPTION,
+                AuthenticationProvider.TIME_TO_LIVE);
+        assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.STATE, State.ACTIVE.name(),
+                provider.get(AuthenticationProvider.STATE));
+        assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.LIFETIME_POLICY,
+                LifetimePolicy.PERMANENT.name(), provider.get(AuthenticationProvider.LIFETIME_POLICY));
+        assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.DURABLE, Boolean.TRUE,
+                provider.get(AuthenticationProvider.DURABLE));
+        assertEquals("Unexpected value of provider attribute " + AuthenticationProvider.TYPE, type,
+                provider.get(AuthenticationProvider.TYPE));
+
+        @SuppressWarnings("unchecked")
+        List> users = (List>) provider.get("users");
+        assertNotNull("Users are not found", users);
+        assertTrue("Unexpected number of users", users.size() > 1);
+        for (Map user : users)
+        {
+            assertNotNull("Attribute " + User.ID, user.get(User.ID));
+            assertNotNull("Attribute " + User.NAME, user.get(User.NAME));
+        }
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java
new file mode 100644
index 0000000000..0574b6cc24
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BasicAuthRestTest.java
@@ -0,0 +1,121 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE;
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.Collections;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+
+public class BasicAuthRestTest extends QpidRestTestCase
+{
+    private static final String USERNAME = "admin";
+
+    @Override
+    public void setUp() throws Exception
+    {
+        setSystemProperty("javax.net.debug", "ssl");
+
+        //don't call super method, we will configure the broker in the test before doing so
+    }
+
+    @Override
+    protected void customizeConfiguration() throws ConfigurationException, IOException
+    {
+        //do nothing, we will configure this locally
+    }
+
+    private void configure(boolean useSsl) throws ConfigurationException, IOException
+    {
+        getRestTestHelper().setUseSsl(useSsl);
+        if (useSsl)
+        {
+            getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.PROTOCOLS, Collections.singleton(Protocol.HTTPS));
+        }
+        super.customizeConfiguration();
+    }
+
+    private void verifyGetBrokerAttempt(int responseCode) throws IOException
+    {
+        HttpURLConnection conn = getRestTestHelper().openManagementConnection("/rest/broker", "GET");
+        assertEquals(responseCode, conn.getResponseCode());
+    }
+
+    public void testDefaultEnabledWithHttps() throws Exception
+    {
+        configure(true);
+        super.setUp();
+        setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
+        setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
+
+        // Try the attempt with authentication, it should succeed because
+        // BASIC auth is enabled by default on secure connections.
+        getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME);
+        verifyGetBrokerAttempt(HttpServletResponse.SC_OK);
+    }
+
+    public void testDefaultDisabledWithHttp() throws Exception
+    {
+        configure(false);
+        super.setUp();
+
+        // Try the attempt with authentication, it should fail because
+        // BASIC auth is disabled by default on non-secure connections.
+        getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME);
+        verifyGetBrokerAttempt(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+    }
+
+    public void testEnablingForHttp() throws Exception
+    {
+        configure(false);
+
+        getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpBasicAuthenticationEnabled", true);
+        super.setUp();
+
+        // Try the attempt with authentication, it should succeed because
+        // BASIC auth is now enabled on non-secure connections.
+        getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME);
+        verifyGetBrokerAttempt(HttpServletResponse.SC_OK);
+    }
+
+    public void testDisablingForHttps() throws Exception
+    {
+        configure(true);
+        getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpsBasicAuthenticationEnabled", false);
+        super.setUp();
+        setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
+        setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
+
+        // Try the attempt with authentication, it should fail because
+        // BASIC auth is now disabled on secure connections.
+        getRestTestHelper().setUsernameAndPassword(USERNAME, USERNAME);
+        verifyGetBrokerAttempt(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java
new file mode 100644
index 0000000000..372db8f560
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java
@@ -0,0 +1,130 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.Binding;
+
+public class BindingRestTest extends QpidRestTestCase
+{
+
+    public void testGetAllBindings() throws Exception
+    {
+        List> bindings = getRestTestHelper().getJsonAsList("/rest/binding");
+        assertNotNull("Bindings cannot be null", bindings);
+        assertTrue("Unexpected number of bindings: " + bindings.size(),
+                bindings.size() >= EXPECTED_VIRTUALHOSTS.length * EXPECTED_QUEUES.length);
+        for (Map binding : bindings)
+        {
+            Asserts.assertBinding((String) binding.get(Binding.NAME), (String) binding.get(Binding.EXCHANGE), binding);
+        }
+    }
+
+    public void testGetVirtualHostBindings() throws Exception
+    {
+        List> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test");
+        assertNotNull("Bindings cannot be null", bindings);
+        assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length * 2, bindings.size());
+        for (String queueName : EXPECTED_QUEUES)
+        {
+            Map searchAttributes = new HashMap();
+            searchAttributes.put(Binding.NAME, queueName);
+            searchAttributes.put(Binding.EXCHANGE, "amq.direct");
+
+            Map binding = getRestTestHelper().find(searchAttributes, bindings);
+            Asserts.assertBinding(queueName, "amq.direct", binding);
+
+            searchAttributes.put(Binding.EXCHANGE, "<>");
+
+            binding = getRestTestHelper().find(searchAttributes, bindings);
+            Asserts.assertBinding(queueName, "<>", binding);
+        }
+    }
+
+    public void testGetVirtualHostExchangeBindings() throws Exception
+    {
+        List> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct");
+        assertNotNull("Bindings cannot be null", bindings);
+        assertEquals("Unexpected number of bindings", EXPECTED_QUEUES.length, bindings.size());
+        for (String queueName : EXPECTED_QUEUES)
+        {
+            Map binding = getRestTestHelper().find(Binding.NAME, queueName, bindings);
+            Asserts.assertBinding(queueName, "amq.direct", binding);
+        }
+    }
+
+    public void testGetVirtualHostExchangeQueueBindings() throws Exception
+    {
+        List> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue");
+        assertNotNull("Bindings cannot be null", bindings);
+        assertEquals("Unexpected number of bindings", 1, bindings.size());
+        Asserts.assertBinding("queue", "amq.direct", bindings.get(0));
+    }
+
+
+    public void testDeleteBinding() throws Exception
+    {
+        List> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue");
+        assertEquals("Unexpected number of bindings", 1, bindings.size());
+        Asserts.assertBinding("queue", "amq.direct", bindings.get(0));
+
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/queue", "DELETE");
+        connection.connect();
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+
+        bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue");
+        assertEquals("Binding should be deleted", 0, bindings.size());
+    }
+
+    public void testDeleteBindingById() throws Exception
+    {
+        Map binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue");
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE");
+        connection.connect();
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+        List> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue");
+        assertEquals("Binding should be deleted", 0, bindings.size());
+    }
+
+    public void testCreateBinding() throws Exception
+    {
+        String bindingName =  getTestName();
+        Map bindingData = new HashMap();
+        bindingData.put(Binding.NAME, bindingName);
+        bindingData.put(Binding.QUEUE, "queue");
+        bindingData.put(Binding.EXCHANGE, "amq.direct");
+
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT");
+        connection.connect();
+        getRestTestHelper().writeJsonRequest(connection, bindingData);
+        int responseCode = connection.getResponseCode();
+        connection.disconnect();
+        assertEquals("Unexpected response code", 201, responseCode);
+        Map binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName);
+
+        Asserts.assertBinding(bindingName, "queue", "amq.direct", binding);
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java
new file mode 100644
index 0000000000..13e0c1e819
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsTest.java
@@ -0,0 +1,69 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE;
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+
+public class BrokerRestHttpsTest extends QpidRestTestCase
+{
+    @Override
+    public void setUp() throws Exception
+    {
+        setSystemProperty("javax.net.debug", "ssl");
+        super.setUp();
+        setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE);
+        setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
+    }
+
+    @Override
+    protected void customizeConfiguration() throws ConfigurationException, IOException
+    {
+        super.customizeConfiguration();
+        getRestTestHelper().setUseSsl(true);
+        Map newAttributes = new HashMap();
+        newAttributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.HTTPS));
+        newAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL));
+        getBrokerConfiguration().setObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT,newAttributes);
+    }
+
+    public void testGetWithHttps() throws Exception
+    {
+        Map brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker");
+
+        Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES, Broker.BYTES_RETAINED,
+                Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES, Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED,
+                Broker.ACL_FILE, Broker.KEY_STORE_CERT_ALIAS, Broker.TRUST_STORE_PATH, Broker.TRUST_STORE_PASSWORD,
+                Broker.GROUP_FILE);
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java
new file mode 100644
index 0000000000..d479d39287
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java
@@ -0,0 +1,120 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.common.QpidProperties;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+
+public class BrokerRestTest extends QpidRestTestCase
+{
+
+    private static final String BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE = "authenticationproviders";
+    private static final String BROKER_PORTS_ATTRIBUTE = "ports";
+    private static final String BROKER_VIRTUALHOSTS_ATTRIBUTE = "virtualhosts";
+    private static final String BROKER_STATISTICS_ATTRIBUTE = "statistics";
+
+    public void testGet() throws Exception
+    {
+        Map brokerDetails = getRestTestHelper().getJsonAsSingletonList("/rest/broker");
+
+        assertBrokerAttributes(brokerDetails);
+
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) brokerDetails.get(BROKER_STATISTICS_ATTRIBUTE);
+        Asserts.assertAttributesPresent(statistics, new String[]{ "bytesIn", "messagesOut", "bytesOut", "messagesIn" });
+
+        @SuppressWarnings("unchecked")
+        List> virtualhosts = (List>) brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE);
+        assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size());
+
+        Asserts.assertVirtualHost(TEST3_VIRTUALHOST, getRestTestHelper().find(VirtualHost.NAME, TEST3_VIRTUALHOST, virtualhosts));
+        Asserts.assertVirtualHost(TEST2_VIRTUALHOST, getRestTestHelper().find(VirtualHost.NAME, TEST2_VIRTUALHOST, virtualhosts));
+        Asserts.assertVirtualHost(TEST1_VIRTUALHOST, getRestTestHelper().find(VirtualHost.NAME, TEST1_VIRTUALHOST, virtualhosts));
+
+        @SuppressWarnings("unchecked")
+        List> ports = (List>) brokerDetails.get(BROKER_PORTS_ATTRIBUTE);
+        assertEquals("Unexpected number of ports", 4, ports.size());
+
+        for (Map port : ports)
+        {
+            Asserts.assertPortAttributes(port);
+        }
+
+        Map amqpPort = getRestTestHelper().find(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT, ports);
+        Map httpPort = getRestTestHelper().find(Port.NAME, TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, ports);
+
+        assertEquals("Unexpected binding address", "*", amqpPort.get(Port.BINDING_ADDRESS));
+        assertNotNull("Cannot find AMQP port", amqpPort);
+        assertNotNull("Cannot find HTTP port", httpPort);
+
+        @SuppressWarnings("unchecked")
+        Collection port1Protocols = (Collection) amqpPort.get(Port.PROTOCOLS);
+        assertFalse("AMQP protocol list cannot contain HTTP", port1Protocols.contains("HTTP"));
+
+        @SuppressWarnings("unchecked")
+        Collection port2Protocols = (Collection) httpPort.get(Port.PROTOCOLS);
+        assertEquals("Unexpected value of attribute " + Port.PROTOCOLS, new HashSet(Arrays.asList("HTTP")),
+                new HashSet(port2Protocols));
+    }
+
+    protected void assertBrokerAttributes(Map brokerDetails)
+    {
+        Asserts.assertAttributesPresent(brokerDetails, Broker.AVAILABLE_ATTRIBUTES,
+                Broker.BYTES_RETAINED, Broker.PROCESS_PID, Broker.SUPPORTED_STORE_TYPES,
+                Broker.CREATED, Broker.TIME_TO_LIVE, Broker.UPDATED, Broker.ACL_FILE,
+                Broker.KEY_STORE_PATH, Broker.KEY_STORE_PASSWORD, Broker.KEY_STORE_CERT_ALIAS,
+                Broker.TRUST_STORE_PATH, Broker.TRUST_STORE_PASSWORD, Broker.GROUP_FILE);
+
+        assertEquals("Unexpected value of attribute " + Broker.BUILD_VERSION, QpidProperties.getBuildVersion(),
+                brokerDetails.get(Broker.BUILD_VERSION));
+        assertEquals("Unexpected value of attribute " + Broker.OPERATING_SYSTEM, System.getProperty("os.name") + " "
+                + System.getProperty("os.version") + " " + System.getProperty("os.arch"),
+                brokerDetails.get(Broker.OPERATING_SYSTEM));
+        assertEquals(
+                "Unexpected value of attribute " + Broker.PLATFORM,
+                System.getProperty("java.vendor") + " "
+                        + System.getProperty("java.runtime.version", System.getProperty("java.version")),
+                brokerDetails.get(Broker.PLATFORM));
+        assertEquals("Unexpected value of attribute " + Broker.DURABLE, Boolean.TRUE, brokerDetails.get(Broker.DURABLE));
+        assertEquals("Unexpected value of attribute " + Broker.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(),
+                brokerDetails.get(Broker.LIFETIME_POLICY));
+        assertEquals("Unexpected value of attribute " + Broker.NAME, "QpidBroker", brokerDetails.get(Broker.NAME));
+        assertEquals("Unexpected value of attribute " + Broker.STATE, State.ACTIVE.name(), brokerDetails.get(Broker.STATE));
+
+        assertNotNull("Unexpected value of attribute " + Broker.ID, brokerDetails.get(Broker.ID));
+        assertNotNull("Unexpected value of attribute statistics", brokerDetails.get(BROKER_STATISTICS_ATTRIBUTE));
+        assertNotNull("Unexpected value of attribute virtualhosts", brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE));
+        assertNotNull("Unexpected value of attribute ports", brokerDetails.get(BROKER_PORTS_ATTRIBUTE));
+        assertNotNull("Unexpected value of attribute authenticationproviders", brokerDetails.get(BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE));
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java
new file mode 100644
index 0000000000..05c8e362a1
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java
@@ -0,0 +1,213 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.IOException;
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.Map;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Session;
+
+public class ConnectionRestTest extends QpidRestTestCase
+{
+    /**
+     * Message number to publish into queue
+     */
+    private static final int MESSAGE_NUMBER = 5;
+    private static final int MESSAGE_SIZE = 6;
+
+    private static final String SESSIONS_ATTRIBUTE = "sessions";
+
+    private javax.jms.Connection _connection;
+    private javax.jms.Session _session;
+
+    public void setUp() throws Exception
+    {
+        super.setUp();
+
+        _connection = getConnection();
+        _session = _connection.createSession(true, javax.jms.Session.SESSION_TRANSACTED);
+        String queueName = getTestQueueName();
+        Destination queue = _session.createQueue(queueName);
+        MessageConsumer consumer = _session.createConsumer(queue);
+        MessageProducer producer = _session.createProducer(queue);
+        _connection.start();
+
+        // send messages
+        for (int i = 0; i < MESSAGE_NUMBER; i++)
+        {
+            producer.send(_session.createTextMessage("Test-" + i));
+        }
+        _session.commit();
+
+        Message m = consumer.receive(1000l);
+        assertNotNull("Message was not received", m);
+        _session.commit();
+
+        // receive the rest of messages for rollback
+        for (int i = 0; i < MESSAGE_NUMBER - 1; i++)
+        {
+            m = consumer.receive(1000l);
+            assertNotNull("Message was not received", m);
+        }
+        _session.rollback();
+
+        // receive them again
+        for (int i = 0; i < MESSAGE_NUMBER - 1; i++)
+        {
+            m = consumer.receive(1000l);
+            assertNotNull("Message was not received", m);
+        }
+    }
+
+    public void testGetAllConnections() throws Exception
+    {
+        List> connections = getRestTestHelper().getJsonAsList("/rest/connection");
+        assertEquals("Unexpected number of connections", 1, connections.size());
+        Asserts.assertConnection(connections.get(0), (AMQConnection) _connection);
+    }
+
+    public void testGetVirtualHostConnections() throws Exception
+    {
+        List> connections = getRestTestHelper().getJsonAsList("/rest/connection/test");
+        assertEquals("Unexpected number of connections", 1, connections.size());
+        Asserts.assertConnection(connections.get(0), (AMQConnection) _connection);
+    }
+
+    public void testGetConnectionByName() throws Exception
+    {
+        // get connection name
+        String connectionName = getConnectionName();
+
+        Map connectionDetails = getRestTestHelper().getJsonAsSingletonList("/rest/connection/test/"
+                + URLDecoder.decode(connectionName, "UTF-8"));
+        assertConnection(connectionDetails);
+    }
+
+    public void testGetAllSessions() throws Exception
+    {
+        List> sessions = getRestTestHelper().getJsonAsList("/rest/session");
+        assertEquals("Unexpected number of sessions", 1, sessions.size());
+        assertSession(sessions.get(0), (AMQSession) _session);
+    }
+
+    public void testGetVirtualHostSessions() throws Exception
+    {
+        List> sessions = getRestTestHelper().getJsonAsList("/rest/session/test");
+        assertEquals("Unexpected number of sessions", 1, sessions.size());
+        assertSession(sessions.get(0), (AMQSession) _session);
+    }
+
+    public void testGetConnectionSessions() throws Exception
+    {
+        // get connection name
+        String connectionName = getConnectionName();
+
+        List> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/"
+                + URLDecoder.decode(connectionName, "UTF-8"));
+        assertEquals("Unexpected number of sessions", 1, sessions.size());
+        assertSession(sessions.get(0), (AMQSession) _session);
+    }
+
+    public void testGetSessionByName() throws Exception
+    {
+        // get connection name
+        String connectionName = getConnectionName();
+
+        List> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/"
+                + URLDecoder.decode(connectionName, "UTF-8") + "/" + ((AMQSession) _session).getChannelId());
+        assertEquals("Unexpected number of sessions", 1, sessions.size());
+        assertSession(sessions.get(0), (AMQSession) _session);
+    }
+
+    private void assertConnection(Map connectionDetails) throws JMSException
+    {
+        Asserts.assertConnection(connectionDetails, (AMQConnection) _connection);
+
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) connectionDetails.get(Asserts.STATISTICS_ATTRIBUTE);
+        assertEquals("Unexpected value of connection statistics attribute " + Connection.BYTES_IN, MESSAGE_NUMBER
+                * MESSAGE_SIZE, statistics.get(Connection.BYTES_IN));
+        assertEquals("Unexpected value of connection statistics attribute " + Connection.BYTES_OUT, MESSAGE_SIZE
+                + ((MESSAGE_NUMBER - 1) * MESSAGE_SIZE) * 2, statistics.get(Connection.BYTES_OUT));
+        assertEquals("Unexpected value of connection statistics attribute " + Connection.MESSAGES_IN, MESSAGE_NUMBER,
+                statistics.get(Connection.MESSAGES_IN));
+        assertEquals("Unexpected value of connection statistics attribute " + Connection.MESSAGES_OUT,
+                MESSAGE_NUMBER * 2 - 1, statistics.get(Connection.MESSAGES_OUT));
+
+        @SuppressWarnings("unchecked")
+        List> sessions = (List>) connectionDetails.get(SESSIONS_ATTRIBUTE);
+        assertNotNull("Sessions cannot be found", sessions);
+        assertEquals("Unexpected number of sessions", 1, sessions.size());
+        assertSession(sessions.get(0), (AMQSession) _session);
+    }
+
+    private void assertSession(Map sessionData, AMQSession session)
+    {
+        assertNotNull("Session map cannot be null", sessionData);
+        Asserts.assertAttributesPresent(sessionData, Session.AVAILABLE_ATTRIBUTES, Session.STATE, Session.DURABLE,
+                Session.LIFETIME_POLICY, Session.TIME_TO_LIVE, Session.CREATED, Session.UPDATED);
+        assertEquals("Unexpecte value of attribute " + Session.NAME, session.getChannelId() + "",
+                sessionData.get(Session.NAME));
+        assertEquals("Unexpecte value of attribute " + Session.PRODUCER_FLOW_BLOCKED, Boolean.FALSE,
+                sessionData.get(Session.PRODUCER_FLOW_BLOCKED));
+        assertEquals("Unexpecte value of attribute " + Session.CHANNEL_ID, session.getChannelId(),
+                sessionData.get(Session.CHANNEL_ID));
+
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) sessionData.get(Asserts.STATISTICS_ATTRIBUTE);
+        Asserts.assertAttributesPresent(statistics, Session.AVAILABLE_STATISTICS, Session.BYTES_IN, Session.BYTES_OUT,
+                Session.STATE_CHANGED, Session.UNACKNOWLEDGED_BYTES, Session.LOCAL_TRANSACTION_OPEN,
+                Session.XA_TRANSACTION_BRANCH_ENDS, Session.XA_TRANSACTION_BRANCH_STARTS,
+                Session.XA_TRANSACTION_BRANCH_SUSPENDS);
+
+        assertEquals("Unexpecte value of statistic attribute " + Session.UNACKNOWLEDGED_MESSAGES, MESSAGE_NUMBER - 1,
+                statistics.get(Session.UNACKNOWLEDGED_MESSAGES));
+        assertEquals("Unexpecte value of statistic attribute " + Session.LOCAL_TRANSACTION_BEGINS, 4,
+                statistics.get(Session.LOCAL_TRANSACTION_BEGINS));
+        assertEquals("Unexpecte value of statistic attribute " + Session.LOCAL_TRANSACTION_ROLLBACKS, 1,
+                statistics.get(Session.LOCAL_TRANSACTION_ROLLBACKS));
+        assertEquals("Unexpecte value of statistic attribute " + Session.CONSUMER_COUNT, 1,
+                statistics.get(Session.CONSUMER_COUNT));
+    }
+
+    private String getConnectionName() throws IOException
+    {
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+        @SuppressWarnings("unchecked")
+        List> connections = (List>) hostDetails
+                .get(VirtualHostRestTest.VIRTUALHOST_CONNECTIONS_ATTRIBUTE);
+        assertEquals("Unexpected number of connections", 1, connections.size());
+        Map connection = connections.get(0);
+        String connectionName = (String) connection.get(Connection.NAME);
+        return connectionName;
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java
new file mode 100644
index 0000000000..ec9791db13
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java
@@ -0,0 +1,87 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Exchange;
+
+public class ExchangeRestTest extends QpidRestTestCase
+{
+    public void testGet() throws Exception
+    {
+        List> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange");
+        assertNotNull("Exchanges cannot be null", exchanges);
+        assertTrue("Unexpected number of exchanges", exchanges.size() >= EXPECTED_VIRTUALHOSTS.length * EXPECTED_EXCHANGES.length);
+        for (Map exchange : exchanges)
+        {
+            Asserts.assertExchange((String) exchange.get(Exchange.NAME), (String) exchange.get(Exchange.TYPE), exchange);
+        }
+    }
+
+    public void testGetHostExchanges() throws Exception
+    {
+        List> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange/test");
+        assertNotNull("Users cannot be null", exchanges);
+        assertEquals("Unexpected number of exchanges", exchanges.size(), EXPECTED_EXCHANGES.length);
+        for (String exchangeName : EXPECTED_EXCHANGES)
+        {
+            Map exchange = getRestTestHelper().find(Exchange.NAME, exchangeName, exchanges);
+            assertExchange(exchangeName, exchange);
+        }
+    }
+
+    public void testGetHostExchangeByName() throws Exception
+    {
+        for (String exchangeName : EXPECTED_EXCHANGES)
+        {
+            Map exchange = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/"
+                    + URLDecoder.decode(exchangeName, "UTF-8"));
+            assertExchange(exchangeName, exchange);
+        }
+    }
+
+    private void assertExchange(String exchangeName, Map exchange)
+    {
+        assertNotNull("Exchange with name " + exchangeName + " is not found", exchange);
+        String type = (String) exchange.get(Exchange.TYPE);
+        Asserts.assertExchange(exchangeName, type, exchange);
+        if ("direct".equals(type))
+        {
+            assertBindings(exchange);
+        }
+    }
+
+    private void assertBindings(Map exchange)
+    {
+        @SuppressWarnings("unchecked")
+        List> bindings = (List>) exchange.get("bindings");
+        for (String queueName : EXPECTED_QUEUES)
+        {
+            Map binding = getRestTestHelper().find(Binding.NAME, queueName, bindings);
+            Asserts.assertBinding(queueName, (String) exchange.get(Exchange.NAME), binding);
+        }
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java
new file mode 100644
index 0000000000..861bf8cb71
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupProviderRestTest.java
@@ -0,0 +1,160 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Group;
+import org.apache.qpid.server.model.GroupProvider;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.UUIDGenerator;
+
+public class GroupProviderRestTest extends QpidRestTestCase
+{
+    private static final String FILE_GROUP_MANAGER = "FileGroupManager";
+    private File _groupFile;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        _groupFile = createTemporaryGroupFile();
+
+        getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath());
+
+        super.setUp();
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        super.tearDown();
+
+        if (_groupFile != null)
+        {
+            if (_groupFile.exists())
+            {
+                _groupFile.delete();
+            }
+        }
+    }
+
+    public void testGet() throws Exception
+    {
+        List> providerDetails = getRestTestHelper().getJsonAsList("/rest/groupprovider");
+        assertNotNull("Providers details cannot be null", providerDetails);
+        assertEquals("Unexpected number of providers", 1, providerDetails.size());
+        for (Map provider : providerDetails)
+        {
+            assertProvider(FILE_GROUP_MANAGER, provider);
+            Map data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/"
+                    + provider.get(GroupProvider.NAME));
+            assertNotNull("Cannot load data for " + provider.get(GroupProvider.NAME), data);
+            assertProvider(FILE_GROUP_MANAGER, data);
+        }
+    }
+
+    public void testCreateNewGroup() throws Exception
+    {
+        String groupName = "newGroup";
+
+        Map data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        assertNotNull("Cannot load data for provider", data);
+
+        getRestTestHelper().assertNumberOfGroups(data, 1);
+
+        getRestTestHelper().createGroup(groupName, FILE_GROUP_MANAGER);
+
+        data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        assertNotNull("Cannot load data for provider", data);
+
+        getRestTestHelper().assertNumberOfGroups(data, 2);
+    }
+
+    public void testRemoveGroup() throws Exception
+    {
+        String groupName = "myGroup";
+
+        Map data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        assertNotNull("Cannot load data for provider", data);
+
+        getRestTestHelper().assertNumberOfGroups(data, 1);
+
+        getRestTestHelper().removeGroup(groupName, FILE_GROUP_MANAGER);
+
+        data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        assertNotNull("Cannot load data for provider", data);
+
+        getRestTestHelper().assertNumberOfGroups(data, 0);
+    }
+
+
+    private void assertProvider(String type, Map provider)
+    {
+        Asserts.assertAttributesPresent(provider, GroupProvider.AVAILABLE_ATTRIBUTES,
+                GroupProvider.CREATED, GroupProvider.UPDATED, GroupProvider.DESCRIPTION,
+                GroupProvider.TIME_TO_LIVE);
+        assertEquals("Unexpected value of provider attribute " + GroupProvider.STATE, State.ACTIVE.name(),
+                provider.get(GroupProvider.STATE));
+        assertEquals("Unexpected value of provider attribute " + GroupProvider.LIFETIME_POLICY,
+                LifetimePolicy.PERMANENT.name(), provider.get(GroupProvider.LIFETIME_POLICY));
+        assertEquals("Unexpected value of provider attribute " + GroupProvider.DURABLE, Boolean.TRUE,
+                provider.get(GroupProvider.DURABLE));
+        assertEquals("Unexpected value of provider attribute " + GroupProvider.TYPE, type,
+                provider.get(GroupProvider.TYPE));
+
+        final String name = (String) provider.get(GroupProvider.NAME);
+        assertEquals("Unexpected value of provider attribute " + GroupProvider.NAME, type,
+                name);
+
+        @SuppressWarnings("unchecked")
+        List> groups = (List>) provider.get("groups");
+        assertNotNull("Groups were not found", groups);
+        assertEquals("Unexpected number of groups", 1, groups.size());
+        for (Map group : groups)
+        {
+
+            final String groupName = (String) group.get(Group.NAME);
+            assertNotNull("Attribute " + Group.NAME, groupName);
+
+            assertNotNull("Attribute " + Group.ID, group.get(Group.ID));
+            assertEquals("Attribute " + Group.ID, UUIDGenerator.generateGroupUUID(name, groupName).toString(), group.get(Group.ID));
+        }
+    }
+
+    private File createTemporaryGroupFile() throws Exception
+    {
+        File groupFile = File.createTempFile("group", "grp");
+        groupFile.deleteOnExit();
+
+        Properties props = new Properties();
+        props.put("myGroup.users", "guest");
+
+        props.store(new FileOutputStream(groupFile), "test group file");
+
+        return groupFile;
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java
new file mode 100644
index 0000000000..d3f93cc0fe
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/GroupRestTest.java
@@ -0,0 +1,109 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.GroupMember;
+
+public class GroupRestTest extends QpidRestTestCase
+{
+    private static final String GROUP_NAME = "myGroup";
+    private static final String FILE_GROUP_MANAGER = "FileGroupManager";
+    private static final String EXISTING_MEMBER = "user1";
+    private static final String NEW_MEMBER = "user2";
+
+    private File _groupFile;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        _groupFile = createTemporaryGroupFile();
+
+        getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath());
+
+        super.setUp();
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        super.tearDown();
+
+        if (_groupFile != null)
+        {
+            if (_groupFile.exists())
+            {
+                _groupFile.delete();
+            }
+        }
+    }
+
+    public void testGet() throws Exception
+    {
+        Map group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+        List> groupmembers = (List>) group.get("groupmembers");
+        assertEquals(1, groupmembers.size());
+
+        Map member1 = groupmembers.get(0);
+        assertEquals(EXISTING_MEMBER, (String)member1.get(GroupMember.NAME));
+    }
+
+    public void testCreateNewMemberOfGroup() throws Exception
+    {
+        Map group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+        getRestTestHelper().assertNumberOfGroupMembers(group, 1);
+
+        getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, GROUP_NAME, NEW_MEMBER);
+
+        group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+        getRestTestHelper().assertNumberOfGroupMembers(group, 2);
+    }
+
+    public void testRemoveMemberFromGroup() throws Exception
+    {
+        Map group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+        getRestTestHelper().assertNumberOfGroupMembers(group, 1);
+
+        getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, GROUP_NAME, EXISTING_MEMBER);
+
+        group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/myGroup");
+        getRestTestHelper().assertNumberOfGroupMembers(group, 0);
+    }
+
+    private File createTemporaryGroupFile() throws Exception
+    {
+        File groupFile = File.createTempFile("group", "grp");
+        groupFile.deleteOnExit();
+
+        Properties props = new Properties();
+        props.put(GROUP_NAME + ".users", EXISTING_MEMBER);
+
+        props.store(new FileOutputStream(groupFile), "test group file");
+
+        return groupFile;
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java
new file mode 100644
index 0000000000..a2f9d3189c
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java
@@ -0,0 +1,42 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.util.List;
+import java.util.Map;
+
+public class LogRecordsRestTest extends QpidRestTestCase
+{
+    public void testGet() throws Exception
+    {
+        List> logs = getRestTestHelper().getJsonAsList("/rest/logrecords");
+        assertNotNull("Logs data cannot be null", logs);
+        assertTrue("Logs are not found", logs.size() > 0);
+        Map record = getRestTestHelper().find("message", "[Broker] BRK-1004 : Qpid Broker Ready", logs);
+
+        assertNotNull("BRK-1004 message is not found", record);
+        assertNotNull("Message id cannot be null", record.get("id"));
+        assertNotNull("Message timestamp cannot be null", record.get("timestamp"));
+        assertEquals("Unexpected log level", "INFO", record.get("level"));
+        assertEquals("Unexpected thread", "main", record.get("thread"));
+        assertEquals("Unexpected logger", "qpid.message.broker.ready", record.get("logger"));
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java
new file mode 100644
index 0000000000..fb6bfca1d8
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java
@@ -0,0 +1,354 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.jms.BytesMessage;
+import javax.jms.Connection;
+import javax.jms.DeliveryMode;
+import javax.jms.Destination;
+import javax.jms.Message;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+
+public class MessagesRestTest extends QpidRestTestCase
+{
+
+    /**
+     * Message number to publish into queue
+     */
+    private static final int MESSAGE_NUMBER = 12;
+
+    private Connection _connection;
+    private Session _session;
+    private MessageProducer _producer;
+    private long _startTime;
+    private long _ttl;
+
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _startTime = System.currentTimeMillis();
+        _connection = getConnection();
+        _session = _connection.createSession(true, Session.SESSION_TRANSACTED);
+        String queueName = getTestQueueName();
+        Destination queue = _session.createQueue(queueName);
+        _session.createConsumer(queue);
+        _producer = _session.createProducer(queue);
+
+        _ttl = TimeUnit.DAYS.toMillis(1);
+        for (int i = 0; i < MESSAGE_NUMBER; i++)
+        {
+            Message m = _session.createTextMessage("Test-" + i);
+            m.setIntProperty("index", i);
+            if (i % 2 == 0)
+            {
+                _producer.send(m);
+            }
+            else
+            {
+                _producer.send(m, DeliveryMode.NON_PERSISTENT, 5, _ttl);
+            }
+        }
+        _session.commit();
+    }
+
+    public void testGet() throws Exception
+    {
+        String queueName = getTestQueueName();
+        List> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName);
+        assertNotNull("Messages are not found", messages);
+        assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size());
+        int position = 0;
+        for (Map message : messages)
+        {
+            assertMessage(position, message);
+            position++;
+        }
+    }
+
+    public void testGetMessageContent() throws Exception
+    {
+        String queueName = getTestQueueName();
+
+        // add bytes message
+        BytesMessage byteMessage = _session.createBytesMessage();
+        byte[] messageBytes = "Test".getBytes();
+        byteMessage.writeBytes(messageBytes);
+        byteMessage.setStringProperty("test", "value");
+        _producer.send(byteMessage);
+        _session.commit();
+
+        // get message IDs
+        List ids = getMesssageIds(queueName);
+
+        Map message = getRestTestHelper().getJsonAsMap("/rest/message/test/" + queueName + "/" + ids.get(0));
+        assertMessageAttributes(message);
+        assertMessageAttributeValues(message, true);
+
+        @SuppressWarnings("unchecked")
+        Map headers = (Map) message.get("headers");
+        assertNotNull("Message headers are not found", headers);
+        assertEquals("Unexpected message header", 0, headers.get("index"));
+
+        Long lastMessageId = ids.get(ids.size() - 1);
+        message = getRestTestHelper().getJsonAsMap("/rest/message/test/" + queueName + "/" + lastMessageId);
+        assertMessageAttributes(message);
+        assertEquals("Unexpected message attribute mimeType", "application/octet-stream", message.get("mimeType"));
+        assertEquals("Unexpected message attribute size", 4, message.get("size"));
+
+        @SuppressWarnings("unchecked")
+        Map bytesMessageHeader = (Map) message.get("headers");
+        assertNotNull("Message headers are not found", bytesMessageHeader);
+        assertEquals("Unexpected message header", "value", bytesMessageHeader.get("test"));
+
+        // get content
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message-content/test/" + queueName + "/"
+                + lastMessageId, "GET");
+        connection.connect();
+        byte[] data = getRestTestHelper().readConnectionInputStream(connection);
+        assertTrue("Unexpected message", Arrays.equals(messageBytes, data));
+
+    }
+
+    public void testPostMoveMessages() throws Exception
+    {
+        String queueName = getTestQueueName();
+        String queueName2 = queueName + "_2";
+        Destination queue2 = _session.createQueue(queueName2);
+        _session.createConsumer(queue2);
+
+        // get message IDs
+        List ids = getMesssageIds(queueName);
+
+        // move half of the messages
+        int movedNumber = ids.size() / 2;
+        List movedMessageIds = new ArrayList();
+        for (int i = 0; i < movedNumber; i++)
+        {
+            movedMessageIds.add(ids.remove(i));
+        }
+
+        // move messages
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message/test/" + queueName, "POST");
+
+        Map messagesData = new HashMap();
+        messagesData.put("messages", movedMessageIds);
+        messagesData.put("destinationQueue", queueName2);
+        messagesData.put("move", Boolean.TRUE);
+
+        getRestTestHelper().writeJsonRequest(connection, messagesData);
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+
+        // check messages on target queue
+        List> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName2);
+        assertNotNull("Messages are not found", messages);
+        assertEquals("Unexpected number of messages", movedMessageIds.size(), messages.size());
+        for (Long id : movedMessageIds)
+        {
+            Map message = getRestTestHelper().find("id", id.intValue(), messages);
+            assertMessageAttributes(message);
+        }
+
+        // check messages on original queue
+        messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName);
+        assertNotNull("Messages are not found", messages);
+        assertEquals("Unexpected number of messages", ids.size(), messages.size());
+        for (Long id : ids)
+        {
+            Map message = getRestTestHelper().find("id", id.intValue(), messages);
+            assertMessageAttributes(message);
+        }
+        for (Long id : movedMessageIds)
+        {
+            Map message = getRestTestHelper().find("id", id.intValue(), messages);
+            assertNull("Moved message " + id + " is found on original queue", message);
+        }
+    }
+
+    public void testPostCopyMessages() throws Exception
+    {
+        String queueName = getTestQueueName();
+        String queueName2 = queueName + "_2";
+        Destination queue2 = _session.createQueue(queueName2);
+        _session.createConsumer(queue2);
+
+        // get message IDs
+        List ids = getMesssageIds(queueName);
+
+        // copy half of the messages
+        int copyNumber = ids.size() / 2;
+        List copyMessageIds = new ArrayList();
+        for (int i = 0; i < copyNumber; i++)
+        {
+            copyMessageIds.add(ids.remove(i));
+        }
+
+        // copy messages
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/message/test/" + queueName, "POST");
+
+        Map messagesData = new HashMap();
+        messagesData.put("messages", copyMessageIds);
+        messagesData.put("destinationQueue", queueName2);
+
+        getRestTestHelper().writeJsonRequest(connection, messagesData);
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+
+        // check messages on target queue
+        List> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName2);
+        assertNotNull("Messages are not found", messages);
+        assertEquals("Unexpected number of messages", copyMessageIds.size(), messages.size());
+        for (Long id : copyMessageIds)
+        {
+            Map message = getRestTestHelper().find("id", id.intValue(), messages);
+            assertMessageAttributes(message);
+        }
+
+        // check messages on original queue
+        messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName);
+        assertNotNull("Messages are not found", messages);
+        assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size());
+        for (Long id : ids)
+        {
+            Map message = getRestTestHelper().find("id", id.intValue(), messages);
+            assertMessageAttributes(message);
+        }
+        for (Long id : copyMessageIds)
+        {
+            Map message = getRestTestHelper().find("id", id.intValue(), messages);
+            assertMessageAttributes(message);
+        }
+    }
+
+    public void testDeleteMessages() throws Exception
+    {
+        String queueName = getTestQueueName();
+
+        // get message IDs
+        List ids = getMesssageIds(queueName);
+
+        // delete half of the messages
+        int deleteNumber = ids.size() / 2;
+        StringBuilder queryString = new StringBuilder();
+        List deleteMessageIds = new ArrayList();
+        for (int i = 0; i < deleteNumber; i++)
+        {
+            Long id = ids.remove(i);
+            deleteMessageIds.add(id);
+            if (queryString.length() > 0)
+            {
+                queryString.append("&");
+            }
+            queryString.append("id=").append(id);
+        }
+
+        // delete messages
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection(
+                "/rest/message/test/" + queueName + "?" + queryString.toString(), "DELETE");
+        connection.connect();
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+
+        // check messages on queue
+        List> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName);
+        assertNotNull("Messages are not found", messages);
+        assertEquals("Unexpected number of messages", ids.size(), messages.size());
+        for (Long id : ids)
+        {
+            Map message = getRestTestHelper().find("id", id.intValue(), messages);
+            assertMessageAttributes(message);
+        }
+        for (Long id : deleteMessageIds)
+        {
+            Map message = getRestTestHelper().find("id", id.intValue(), messages);
+            assertNull("Message with id " + id + " was not deleted", message);
+        }
+    }
+
+    private List getMesssageIds(String queueName) throws IOException, JsonParseException, JsonMappingException
+    {
+        List> messages = getRestTestHelper().getJsonAsList("/rest/message/test/" + queueName);
+        List ids = new ArrayList();
+        for (Map message : messages)
+        {
+            ids.add(((Number) message.get("id")).longValue());
+        }
+        return ids;
+    }
+
+    private void assertMessage(int position, Map message)
+    {
+        assertMessageAttributes(message);
+
+        assertEquals("Unexpected message attribute position", position, message.get("position"));
+        assertEquals("Unexpected message attribute size", position < 10 ? 6 : 7, message.get("size"));
+        boolean even = position % 2 == 0;
+        assertMessageAttributeValues(message, even);
+    }
+
+    private void assertMessageAttributeValues(Map message, boolean even)
+    {
+        if (even)
+        {
+            assertEquals("Unexpected message attribute expirationTime", 0, message.get("expirationTime"));
+            assertEquals("Unexpected message attribute priority", 4, message.get("priority"));
+            assertEquals("Unexpected message attribute persistent", Boolean.TRUE, message.get("persistent"));
+        }
+        else
+        {
+            assertEquals("Unexpected message attribute expirationTime", ((Number) message.get("timestamp")).longValue()
+                    + _ttl, message.get("expirationTime"));
+            assertEquals("Unexpected message attribute priority", 5, message.get("priority"));
+            assertEquals("Unexpected message attribute persistent", Boolean.FALSE, message.get("persistent"));
+        }
+        assertEquals("Unexpected message attribute mimeType", "text/plain", message.get("mimeType"));
+        assertEquals("Unexpected message attribute userId", "guest", message.get("userId"));
+        assertEquals("Unexpected message attribute deliveryCount", 0, message.get("deliveryCount"));
+        assertEquals("Unexpected message attribute state", "Available", message.get("state"));
+    }
+
+    private void assertMessageAttributes(Map message)
+    {
+        assertNotNull("Message map cannot be null", message);
+        assertNotNull("Unexpected message attribute deliveryCount", message.get("deliveryCount"));
+        assertNotNull("Unexpected message attribute state", message.get("state"));
+        assertNotNull("Unexpected message attribute id", message.get("id"));
+        assertNotNull("Message arrivalTime cannot be null", message.get("arrivalTime"));
+        assertNotNull("Message timestamp cannot be null", message.get("timestamp"));
+        assertTrue("Message arrivalTime cannot be null", ((Number) message.get("arrivalTime")).longValue() > _startTime);
+        assertNotNull("Message messageId cannot be null", message.get("messageId"));
+        assertNotNull("Unexpected message attribute mimeType", message.get("mimeType"));
+        assertNotNull("Unexpected message attribute userId", message.get("userId"));
+        assertNotNull("Message priority cannot be null", message.get("priority"));
+        assertNotNull("Message expirationTime cannot be null", message.get("expirationTime"));
+        assertNotNull("Message persistent cannot be null", message.get("persistent"));
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
new file mode 100644
index 0000000000..578565be05
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/PortRestTest.java
@@ -0,0 +1,64 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.net.URLDecoder;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+
+public class PortRestTest extends QpidRestTestCase
+{
+    public void testGet() throws Exception
+    {
+        List> ports = getRestTestHelper().getJsonAsList("/rest/port/");
+        assertNotNull("Port data cannot be null", ports);
+        assertEquals("Unexpected number of ports", 4, ports.size());
+
+        String httpPortName = TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT;
+        Map portData = getRestTestHelper().find(Port.NAME, httpPortName, ports);
+        assertNotNull("Http port " + httpPortName + " is not found", portData);
+        Asserts.assertPortAttributes(portData);
+
+        String amqpPortName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT;
+        Map amqpPortData = getRestTestHelper().find(Port.NAME, amqpPortName, ports);
+        assertNotNull("Amqp port " + amqpPortName + " is not found", amqpPortData);
+        Asserts.assertPortAttributes(amqpPortData);
+    }
+
+    public void testGetPort() throws Exception
+    {
+        List> ports = getRestTestHelper().getJsonAsList("/rest/port/");
+        assertNotNull("Ports data cannot be null", ports);
+        assertEquals("Unexpected number of ports", 4, ports.size());
+        for (Map portMap : ports)
+        {
+            String portName = (String) portMap.get(Port.NAME);
+            assertNotNull("Port name attribute is not found", portName);
+            Map portData = getRestTestHelper().getJsonAsSingletonList("/rest/port/" + URLDecoder.decode(portName, "UTF-8"));
+            assertNotNull("Port " + portName + " is not found", portData);
+            Asserts.assertPortAttributes(portData);
+        }
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java
new file mode 100644
index 0000000000..671bdd7eb8
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.IOException;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+
+public class QpidRestTestCase extends QpidBrokerTestCase
+{
+    public static final String TEST1_VIRTUALHOST = "test";
+    public static final String TEST2_VIRTUALHOST = "test2";
+    public static final String TEST3_VIRTUALHOST = "test3";
+
+    public static final String[] EXPECTED_VIRTUALHOSTS = { TEST1_VIRTUALHOST, TEST2_VIRTUALHOST, TEST3_VIRTUALHOST};
+    public static final String[] EXPECTED_QUEUES = { "queue", "ping" };
+    public static final String[] EXPECTED_EXCHANGES = { "amq.fanout", "amq.match", "amq.direct","amq.topic","<>" };
+
+    private RestTestHelper _restTestHelper = new RestTestHelper(findFreePort());
+
+    @Override
+    public void setUp() throws Exception
+    {
+        // Set up virtualhost config with queues and bindings to the amq.direct
+        for (String virtualhost : EXPECTED_VIRTUALHOSTS)
+        {
+            createTestVirtualHost(0, virtualhost);
+            for (String queue : EXPECTED_QUEUES)
+            {
+                setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".queues.exchange", "amq.direct");
+                setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".queues.queue(-1).name", queue);
+            }
+        }
+
+        customizeConfiguration();
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception
+    {
+        try
+        {
+            super.tearDown();
+        }
+        finally
+        {
+            getRestTestHelper().tearDown();
+        }
+    }
+
+    protected void customizeConfiguration() throws ConfigurationException, IOException
+    {
+        TestBrokerConfiguration config = getBrokerConfiguration();
+        config.addHttpManagementConfiguration();
+        config.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.PORT, _restTestHelper.getHttpPort());
+    }
+
+    public RestTestHelper getRestTestHelper()
+    {
+        return _restTestHelper;
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java
new file mode 100644
index 0000000000..1f441e7cbb
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java
@@ -0,0 +1,225 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.Consumer;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.Queue;
+
+public class QueueRestTest extends QpidRestTestCase
+{
+    private static final String QUEUE_ATTRIBUTE_CONSUMERS = "consumers";
+    private static final String QUEUE_ATTRIBUTE_BINDINGS = "bindings";
+
+    /**
+     * Message number to publish into queue
+     */
+    private static final int MESSAGE_NUMBER = 2;
+    private static final int MESSAGE_PAYLOAD_SIZE = 6;
+    private static final int ENQUEUED_MESSAGES = 1;
+    private static final int DEQUEUED_MESSAGES = 1;
+    private static final int ENQUEUED_BYTES = MESSAGE_PAYLOAD_SIZE;
+    private static final int DEQUEUED_BYTES = MESSAGE_PAYLOAD_SIZE;
+
+    private Connection _connection;
+
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        _connection = getConnection();
+        Session session = _connection.createSession(true, Session.SESSION_TRANSACTED);
+        String queueName = getTestQueueName();
+        Destination queue = session.createQueue(queueName);
+        MessageConsumer consumer = session.createConsumer(queue);
+        MessageProducer producer = session.createProducer(queue);
+
+        for (int i = 0; i < MESSAGE_NUMBER; i++)
+        {
+            producer.send(session.createTextMessage("Test-" + i));
+        }
+        session.commit();
+        _connection.start();
+        Message m = consumer.receive(1000l);
+        assertNotNull("Message is not received", m);
+        session.commit();
+    }
+
+    public void testGetVirtualHostQueues() throws Exception
+    {
+        String queueName = getTestQueueName();
+        List> queues = getRestTestHelper().getJsonAsList("/rest/queue/test");
+        assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length + 1, queues.size());
+        String[] expectedQueues = new String[EXPECTED_QUEUES.length + 1];
+        System.arraycopy(EXPECTED_QUEUES, 0, expectedQueues, 0, EXPECTED_QUEUES.length);
+        expectedQueues[EXPECTED_QUEUES.length] = queueName;
+
+        for (String name : expectedQueues)
+        {
+            Map queueDetails = getRestTestHelper().find(Queue.NAME, name, queues);
+            Asserts.assertQueue(name, "standard", queueDetails);
+
+            @SuppressWarnings("unchecked")
+            List> bindings = (List>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS);
+            assertNotNull("Queue bindings are not found", bindings);
+            assertEquals("Unexpected number of bindings", 2, bindings.size());
+
+            Map defaultExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "<>", bindings);
+            Map directExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "amq.direct", bindings);
+            Asserts.assertBinding(name, "<>", defaultExchangeBinding);
+            Asserts.assertBinding(name, "amq.direct", directExchangeBinding);
+        }
+    }
+
+    public void testGetByName() throws Exception
+    {
+        String queueName = getTestQueueName();
+        Map queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName);
+        Asserts.assertQueue(queueName, "standard", queueDetails);
+        assertStatistics(queueDetails);
+
+        @SuppressWarnings("unchecked")
+        List> bindings = (List>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS);
+        assertNotNull("Queue bindings are not found", bindings);
+        assertEquals("Unexpected number of bindings", 2, bindings.size());
+
+        Map defaultExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "<>", bindings);
+        Map directExchangeBinding = getRestTestHelper().find(Binding.EXCHANGE, "amq.direct", bindings);
+        Asserts.assertBinding(queueName, "<>", defaultExchangeBinding);
+        Asserts.assertBinding(queueName, "amq.direct", directExchangeBinding);
+
+        @SuppressWarnings("unchecked")
+        List> consumers = (List>) queueDetails.get(QUEUE_ATTRIBUTE_CONSUMERS);
+        assertNotNull("Queue consumers are not found", consumers);
+        assertEquals("Unexpected number of consumers", 1, consumers.size());
+        assertConsumer(consumers.get(0));
+    }
+
+    public void testPutCreateBinding() throws Exception
+    {
+        String queueName = getTestQueueName();
+        String bindingName = queueName + 2;
+        String[] exchanges = { "amq.direct", "amq.fanout", "amq.topic", "amq.match", "<>" };
+
+        for (int i = 0; i < exchanges.length; i++)
+        {
+            createBinding(bindingName, exchanges[i], queueName);
+        }
+
+        Map queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName);
+        Asserts.assertQueue(queueName, "standard", queueDetails);
+
+        @SuppressWarnings("unchecked")
+        List> bindings = (List>) queueDetails.get(QUEUE_ATTRIBUTE_BINDINGS);
+        assertNotNull("Queue bindings are not found", bindings);
+        assertEquals("Unexpected number of bindings", exchanges.length + 2, bindings.size());
+
+        Map searchAttributes = new HashMap();
+        searchAttributes.put(Binding.NAME, bindingName);
+
+        for (int i = 0; i < exchanges.length; i++)
+        {
+            searchAttributes.put(Binding.EXCHANGE, exchanges[i]);
+            Map binding = getRestTestHelper().find(searchAttributes, bindings);
+            Asserts.assertBinding(bindingName, queueName, exchanges[i], binding);
+        }
+    }
+
+    private void createBinding(String bindingName, String exchangeName, String queueName) throws IOException
+    {
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection(
+                "/rest/binding/test/" + URLDecoder.decode(exchangeName, "UTF-8") + "/" + queueName + "/" + bindingName,
+                "PUT");
+
+        Map bindingData = new HashMap();
+        bindingData.put(Binding.NAME, bindingName);
+        bindingData.put(Binding.EXCHANGE, exchangeName);
+        bindingData.put(Binding.QUEUE, queueName);
+
+        getRestTestHelper().writeJsonRequest(connection, bindingData);
+        assertEquals("Unexpected response code", 201, connection.getResponseCode());
+
+        connection.disconnect();
+    }
+
+    private void assertConsumer(Map consumer)
+    {
+        assertNotNull("Consumer map should not be null", consumer);
+        Asserts.assertAttributesPresent(consumer, Consumer.AVAILABLE_ATTRIBUTES, Consumer.STATE, Consumer.TIME_TO_LIVE,
+                Consumer.CREATED, Consumer.UPDATED, Consumer.SETTLEMENT_MODE, Consumer.EXCLUSIVE, Consumer.SELECTOR,
+                Consumer.NO_LOCAL);
+
+        assertEquals("Unexpected binding attribute " + Consumer.NAME, "1", consumer.get(Consumer.NAME));
+        assertEquals("Unexpected binding attribute " + Consumer.DURABLE, Boolean.FALSE, consumer.get(Consumer.DURABLE));
+        assertEquals("Unexpected binding attribute " + Consumer.LIFETIME_POLICY, LifetimePolicy.AUTO_DELETE.name(),
+                consumer.get(Consumer.LIFETIME_POLICY));
+        assertEquals("Unexpected binding attribute " + Consumer.DISTRIBUTION_MODE, "MOVE",
+                consumer.get(Consumer.DISTRIBUTION_MODE));
+
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) consumer.get(Asserts.STATISTICS_ATTRIBUTE);
+        assertNotNull("Consumer statistics is not present", statistics);
+        Asserts.assertAttributesPresent(statistics, Consumer.AVAILABLE_STATISTICS, Consumer.STATE_CHANGED);
+    }
+
+    private void assertStatistics(Map queueDetails)
+    {
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) queueDetails.get(Asserts.STATISTICS_ATTRIBUTE);
+        assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES,
+                statistics.get(Queue.PERSISTENT_DEQUEUED_MESSAGES));
+        assertEquals("Unexpected queue statistics attribute " + Queue.QUEUE_DEPTH_MESSAGES, ENQUEUED_MESSAGES,
+                statistics.get(Queue.QUEUE_DEPTH_MESSAGES));
+        assertEquals("Unexpected queue statistics attribute " + Queue.CONSUMER_COUNT, 1,
+                statistics.get(Queue.CONSUMER_COUNT));
+        assertEquals("Unexpected queue statistics attribute " + Queue.CONSUMER_COUNT_WITH_CREDIT, 1,
+                statistics.get(Queue.CONSUMER_COUNT_WITH_CREDIT));
+        assertEquals("Unexpected queue statistics attribute " + Queue.BINDING_COUNT, 2, statistics.get(Queue.BINDING_COUNT));
+        assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES,
+                statistics.get(Queue.PERSISTENT_DEQUEUED_MESSAGES));
+        assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_DEQUEUED_MESSAGES, DEQUEUED_MESSAGES,
+                statistics.get(Queue.TOTAL_DEQUEUED_MESSAGES));
+        assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_DEQUEUED_BYTES, DEQUEUED_BYTES,
+                statistics.get(Queue.TOTAL_DEQUEUED_BYTES));
+        assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_DEQUEUED_BYTES, DEQUEUED_BYTES,
+                statistics.get(Queue.TOTAL_DEQUEUED_BYTES));
+        assertEquals("Unexpected queue statistics attribute " + Queue.PERSISTENT_ENQUEUED_BYTES, ENQUEUED_BYTES
+                + DEQUEUED_BYTES, statistics.get(Queue.PERSISTENT_ENQUEUED_BYTES));
+        assertEquals("Unexpected queue statistics attribute " + Queue.TOTAL_ENQUEUED_BYTES, ENQUEUED_BYTES + DEQUEUED_BYTES,
+                statistics.get(Queue.TOTAL_ENQUEUED_BYTES));
+        assertEquals("Unexpected queue statistics attribute " + Queue.QUEUE_DEPTH_BYTES, ENQUEUED_BYTES,
+                statistics.get(Queue.QUEUE_DEPTH_BYTES));
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java
new file mode 100644
index 0000000000..0db1f7e50d
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java
@@ -0,0 +1,452 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.rest;
+
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE;
+import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD;
+
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.Assert;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.server.security.auth.manager.AbstractPrincipalDatabaseAuthManagerFactory;
+import org.apache.qpid.ssl.SSLContextFactory;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+
+public class RestTestHelper
+{
+    private static final Logger LOGGER = Logger.getLogger(RestTestHelper.class);
+
+    private int _httpPort;
+
+    private boolean _useSsl;
+
+    private String _username;
+
+    private String _password;
+
+    private File _passwdFile;
+
+    public RestTestHelper(int httpPort)
+    {
+        _httpPort = httpPort;
+    }
+
+    public int getHttpPort()
+    {
+        return _httpPort;
+    }
+
+    private String getHostName()
+    {
+        return "localhost";
+    }
+
+    private String getProtocol()
+    {
+        return _useSsl ? "https" : "http";
+    }
+
+    public String getManagementURL()
+    {
+        return getProtocol() + "://" + getHostName() + ":" + getHttpPort();
+    }
+
+    public URL getManagementURL(String path) throws MalformedURLException
+    {
+        return new URL(getManagementURL() + path);
+    }
+
+    public HttpURLConnection openManagementConnection(String path, String method) throws IOException
+    {
+        URL url = getManagementURL(path);
+        HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
+        if(_useSsl)
+        {
+            try
+            {
+                // We have to use a SSLSocketFactory from a new SSLContext so that we don't re-use
+                // the JVM's defaults that may have been initialised in previous tests.
+
+                SSLContext sslContext = SSLContextFactory.buildClientContext(
+                        TRUSTSTORE, TRUSTSTORE_PASSWORD,
+                        KeyStore.getDefaultType(),
+                        TrustManagerFactory.getDefaultAlgorithm(),
+                        null, null, null, null, null);
+
+                SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+
+                ((HttpsURLConnection) httpCon).setSSLSocketFactory(sslSocketFactory);
+            }
+            catch (GeneralSecurityException e)
+            {
+                throw new RuntimeException(e);
+            }
+        }
+
+        if(_username != null)
+        {
+            String encoded = new String(new Base64().encode((_username + ":" + _password).getBytes()));
+            httpCon.setRequestProperty("Authorization", "Basic " + encoded);
+        }
+
+        httpCon.setDoOutput(true);
+        httpCon.setRequestMethod(method);
+        return httpCon;
+    }
+
+    public List> readJsonResponseAsList(HttpURLConnection connection) throws IOException,
+            JsonParseException, JsonMappingException
+    {
+        byte[] data = readConnectionInputStream(connection);
+
+        ObjectMapper mapper = new ObjectMapper();
+
+        TypeReference>> typeReference = new TypeReference>>()
+        {
+        };
+        List> providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference);
+        return providedObject;
+    }
+
+    public Map readJsonResponseAsMap(HttpURLConnection connection) throws IOException,
+            JsonParseException, JsonMappingException
+    {
+        byte[] data = readConnectionInputStream(connection);
+
+        ObjectMapper mapper = new ObjectMapper();
+
+        TypeReference> typeReference = new TypeReference>()
+        {
+        };
+        Map providedObject = mapper.readValue(new ByteArrayInputStream(data), typeReference);
+        return providedObject;
+    }
+
+    public byte[] readConnectionInputStream(HttpURLConnection connection) throws IOException
+    {
+        InputStream is = connection.getInputStream();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int len = -1;
+        while ((len = is.read(buffer)) != -1)
+        {
+            baos.write(buffer, 0, len);
+        }
+        if (LOGGER.isTraceEnabled())
+        {
+            LOGGER.trace("RESPONSE:" + new String(baos.toByteArray()));
+        }
+        return baos.toByteArray();
+    }
+
+    public void writeJsonRequest(HttpURLConnection connection, Map data) throws JsonGenerationException,
+            JsonMappingException, IOException
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.writeValue(connection.getOutputStream(), data);
+    }
+
+    public Map find(String name, Object value, List> data)
+    {
+        for (Map map : data)
+        {
+            Object mapValue = map.get(name);
+            if (value.equals(mapValue))
+            {
+                return map;
+            }
+        }
+        return null;
+    }
+
+    public Map find(Map searchAttributes, List> data)
+    {
+        for (Map map : data)
+        {
+            boolean equals = true;
+            for (Map.Entry entry : searchAttributes.entrySet())
+            {
+                Object mapValue = map.get(entry.getKey());
+                if (!entry.getValue().equals(mapValue))
+                {
+                    equals = false;
+                    break;
+                }
+            }
+            if (equals)
+            {
+                return map;
+            }
+        }
+        return null;
+    }
+
+    public Map getJsonAsSingletonList(String path) throws IOException
+    {
+        List> response = getJsonAsList(path);
+
+        Assert.assertNotNull("Response cannot be null", response);
+        Assert.assertEquals("Unexpected response", 1, response.size());
+        return response.get(0);
+    }
+
+    public List> getJsonAsList(String path) throws IOException, JsonParseException,
+            JsonMappingException
+    {
+        HttpURLConnection connection = openManagementConnection(path, "GET");
+        connection.connect();
+        List> response = readJsonResponseAsList(connection);
+        return response;
+    }
+
+    public Map getJsonAsMap(String path) throws IOException
+    {
+        HttpURLConnection connection = openManagementConnection(path, "GET");
+        connection.connect();
+        Map response = readJsonResponseAsMap(connection);
+        return response;
+    }
+
+    public void createNewGroupMember(String groupProviderName, String groupName, String memberName, int responseCode) throws IOException
+    {
+        HttpURLConnection connection = openManagementConnection(
+                "/rest/groupmember/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8") + "/" +  URLDecoder.decode(memberName, "UTF-8"),
+                "PUT");
+
+        Map groupMemberData = new HashMap();
+        // TODO add type
+        writeJsonRequest(connection, groupMemberData);
+
+        Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode());
+
+        connection.disconnect();
+    }
+
+    public void createNewGroupMember(String groupProviderName, String groupName, String memberName) throws IOException
+    {
+        createNewGroupMember(groupProviderName, groupName, memberName, HttpServletResponse.SC_CREATED);
+    }
+
+    public void removeMemberFromGroup(String groupProviderName, String groupName, String memberName, int responseCode) throws IOException
+    {
+        HttpURLConnection connection = openManagementConnection(
+                "/rest/groupmember/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8") + "/" +  URLDecoder.decode(memberName, "UTF-8"),
+                "DELETE");
+
+        Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode());
+
+        connection.disconnect();
+    }
+
+    public void removeMemberFromGroup(String groupProviderName, String groupName, String memberName) throws IOException
+    {
+        removeMemberFromGroup(groupProviderName, groupName, memberName, HttpServletResponse.SC_OK);
+    }
+
+    public void assertNumberOfGroupMembers(Map data, int expectedNumberOfGroupMembers)
+    {
+        @SuppressWarnings("unchecked")
+        List> groups = (List>) data.get("groupmembers");
+        if (groups == null)
+        {
+            groups = Collections.emptyList();
+        }
+
+        Assert.assertEquals("Unexpected number of group members", expectedNumberOfGroupMembers, groups.size());
+    }
+
+    public void createGroup(String groupName, String groupProviderName) throws IOException
+    {
+        createGroup(groupName, groupProviderName, HttpServletResponse.SC_CREATED);
+    }
+
+    public void createGroup(String groupName, String groupProviderName, int responseCode) throws IOException
+    {
+        HttpURLConnection connection = openManagementConnection(
+                "/rest/group/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8"),
+                "PUT");
+
+        Map groupData = new HashMap();
+        writeJsonRequest(connection, groupData);
+
+        Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode());
+
+        connection.disconnect();
+    }
+
+    public void createOrUpdateUser(String username, String password) throws IOException
+    {
+        createOrUpdateUser(username, password, HttpServletResponse.SC_CREATED);
+    }
+
+    public void createOrUpdateUser(String username, String password, int responseCode) throws IOException
+    {
+        HttpURLConnection connection = openManagementConnection("/rest/user/"
+                + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + username, "PUT");
+
+        Map data = new HashMap();
+        data.put("password", password);
+        writeJsonRequest(connection, data);
+
+        Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode());
+
+        connection.disconnect();
+    }
+
+    public void removeGroup(String groupName, String groupProviderName, int responseCode) throws IOException
+    {
+        HttpURLConnection connection = openManagementConnection(
+                "/rest/group/" + URLDecoder.decode(groupProviderName, "UTF-8") + "/"+ URLDecoder.decode(groupName, "UTF-8"),
+                "DELETE");
+
+        Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode());
+        connection.disconnect();
+    }
+
+    public void removeGroup(String groupName, String groupProviderName) throws IOException
+    {
+        removeGroup(groupName, groupProviderName, HttpServletResponse.SC_OK);
+    }
+
+    public void removeUserById(String id) throws IOException
+    {
+        HttpURLConnection connection = openManagementConnection("/rest/user/"
+                + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "?id=" + id, "DELETE");
+        Assert.assertEquals("Unexpected response code", HttpServletResponse.SC_OK, connection.getResponseCode());
+        connection.disconnect();
+    }
+
+    public void removeUser(String username, int responseCode) throws IOException
+    {
+        HttpURLConnection connection = openManagementConnection("/rest/user/"
+                + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + username, "DELETE");
+        Assert.assertEquals("Unexpected response code", responseCode, connection.getResponseCode());
+        connection.disconnect();
+    }
+
+    public void removeUser(String username) throws IOException
+    {
+        removeUser(username, HttpServletResponse.SC_OK);
+    }
+
+    public void assertNumberOfGroups(Map data, int expectedNumberOfGroups)
+    {
+        @SuppressWarnings("unchecked")
+        List> groups = (List>) data.get("groups");
+        if (groups == null)
+        {
+            groups = Collections.emptyList();
+        }
+        Assert.assertEquals("Unexpected number of groups", expectedNumberOfGroups, groups.size());
+    }
+
+    public void setUseSsl(boolean useSsl)
+    {
+        _useSsl = useSsl;
+    }
+
+    public void setUsernameAndPassword(String username, String password)
+    {
+        _username = username;
+        _password = password;
+    }
+
+    /**
+     * Create password file that follows the convention username=password, which is deleted by {@link #tearDown()}
+     */
+    public void configureTemporaryPasswordFile(QpidBrokerTestCase testCase, String... users) throws ConfigurationException, IOException
+    {
+        _passwdFile = createTemporaryPasswdFile(users);
+
+        testCase.getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER,
+                AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, _passwdFile.getAbsolutePath());
+    }
+
+    public void tearDown()
+    {
+        if (_passwdFile != null)
+        {
+            if (_passwdFile.exists())
+            {
+                _passwdFile.delete();
+            }
+        }
+    }
+
+    private File createTemporaryPasswdFile(String[] users) throws IOException
+    {
+        BufferedWriter writer = null;
+        try
+        {
+            File testFile = File.createTempFile(this.getClass().getName(),"tmp");
+            testFile.deleteOnExit();
+
+            writer = new BufferedWriter(new FileWriter(testFile));
+            for (int i = 0; i < users.length; i++)
+            {
+                String username = users[i];
+                writer.write(username + ":" + username);
+                writer.newLine();
+            }
+
+            return testFile;
+
+        }
+        finally
+        {
+            if (writer != null)
+            {
+                writer.close();
+            }
+        }
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java
new file mode 100644
index 0000000000..856fda9419
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java
@@ -0,0 +1,435 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
+import org.apache.qpid.server.security.auth.manager.AbstractPrincipalDatabaseAuthManagerFactory;
+import org.apache.qpid.server.security.auth.manager.Base64MD5PasswordFileAuthenticationManagerFactory;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.apache.qpid.tools.security.Passwd;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+
+public class SaslRestTest extends QpidRestTestCase
+{
+    @Override
+    public void startBroker()
+    {
+        // prevent broker from starting in setUp
+    }
+
+    public void startBrokerNow() throws Exception
+    {
+        super.startBroker();
+    }
+
+    public void testGetMechanismsWithBrokerPlainPasswordPrincipalDatabase() throws Exception
+    {
+        startBrokerNow();
+
+        Map saslData = getRestTestHelper().getJsonAsMap("/rest/sasl");
+        assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms"));
+
+        @SuppressWarnings("unchecked")
+        List mechanisms = (List) saslData.get("mechanisms");
+        String[] expectedMechanisms = { "AMQPLAIN", "PLAIN", "CRAM-MD5" };
+        for (String mechanism : expectedMechanisms)
+        {
+            assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism));
+        }
+        assertNull("Unexpected user was returned", saslData.get("user"));
+    }
+
+    public void testGetMechanismsWithBrokerBase64MD5FilePrincipalDatabase() throws Exception
+    {
+        configureBase64MD5FilePrincipalDatabase();
+        startBrokerNow();
+
+        Map saslData = getRestTestHelper().getJsonAsMap("/rest/sasl");
+        assertNotNull("mechanisms attribute is not found", saslData.get("mechanisms"));
+
+        @SuppressWarnings("unchecked")
+        List mechanisms = (List) saslData.get("mechanisms");
+        String[] expectedMechanisms = { "CRAM-MD5-HEX", "CRAM-MD5-HASHED" };
+        for (String mechanism : expectedMechanisms)
+        {
+            assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism));
+        }
+        assertNull("Unexpected user was returned", saslData.get("user"));
+    }
+
+    public void testPlainSaslAuthenticationForValidCredentials() throws Exception
+    {
+        startBrokerNow();
+
+        byte[] responseBytes = generatePlainClientResponse("admin", "admin");
+        String responseData = Base64.encodeBase64String(responseBytes);
+        String parameters= "mechanism=PLAIN&response=" + responseData;
+
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST");
+        OutputStream os = connection.getOutputStream();
+        os.write(parameters.getBytes());
+        os.flush();
+
+         int code = connection.getResponseCode();
+        assertEquals("Unexpected response code", 200, code);
+
+        List cookies = connection.getHeaderFields().get("Set-Cookie");
+
+        // request authenticated user details
+        connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
+        applyCookiesToConnection(cookies, connection);
+        Map response2 = getRestTestHelper().readJsonResponseAsMap(connection);
+        assertEquals("Unexpected user", "admin", response2.get("user"));
+    }
+
+    public void testPlainSaslAuthenticationForIncorrectPassword() throws Exception
+    {
+        startBrokerNow();
+
+        byte[] responseBytes = generatePlainClientResponse("admin", "incorrect");
+        String responseData = Base64.encodeBase64String(responseBytes);
+        String parameters= "mechanism=PLAIN&response=" + responseData;
+
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST");
+        OutputStream os = connection.getOutputStream();
+        os.write(parameters.getBytes());
+        os.flush();
+
+        int code = connection.getResponseCode();
+        assertEquals("Unexpected response code", 403, code);
+
+        List cookies = connection.getHeaderFields().get("Set-Cookie");
+
+        // request authenticated user details
+        connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
+        applyCookiesToConnection(cookies, connection);
+        Map response2 = getRestTestHelper().readJsonResponseAsMap(connection);
+        assertNull("Unexpected user", response2.get("user"));
+    }
+
+    public void testPlainSaslAuthenticationForNonExistingUser() throws Exception
+    {
+        startBrokerNow();
+
+        byte[] responseBytes = generatePlainClientResponse("nonexisting", "admin");
+        String responseData = Base64.encodeBase64String(responseBytes);
+        String parameters= "mechanism=PLAIN&response=" + responseData;
+
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST");
+        OutputStream os = connection.getOutputStream();
+        os.write(parameters.getBytes());
+        os.flush();
+
+        int code = connection.getResponseCode();
+        assertEquals("Unexpected response code", 403, code);
+
+        List cookies = connection.getHeaderFields().get("Set-Cookie");
+
+        // request authenticated user details
+        connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
+        applyCookiesToConnection(cookies, connection);
+        Map response2 = getRestTestHelper().readJsonResponseAsMap(connection);
+        assertNull("Unexpected user", response2.get("user"));
+    }
+
+    public void testCramMD5SaslAuthenticationForValidCredentials() throws Exception
+    {
+        startBrokerNow();
+
+        // request the challenge for CRAM-MD5
+        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5");
+        List cookies = connection.getHeaderFields().get("Set-Cookie");
+
+        // authenticate user with correct credentials
+        int code = authenticateUser(connection, "admin", "admin", "CRAM-MD5");
+        assertEquals("Unexpected response code", 200, code);
+
+        // request authenticated user details
+        connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
+        applyCookiesToConnection(cookies, connection);
+        Map response2 = getRestTestHelper().readJsonResponseAsMap(connection);
+        assertEquals("Unexpected user", "admin", response2.get("user"));
+    }
+
+    public void testCramMD5SaslAuthenticationForIncorrectPassword() throws Exception
+    {
+        startBrokerNow();
+
+        // request the challenge for CRAM-MD5
+        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5");
+        List cookies = connection.getHeaderFields().get("Set-Cookie");
+
+        // authenticate user with correct credentials
+        int code = authenticateUser(connection, "admin", "incorrect", "CRAM-MD5");
+        assertEquals("Unexpected response code", 403, code);
+
+        // request authenticated user details
+        connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
+        applyCookiesToConnection(cookies, connection);
+        Map response2 = getRestTestHelper().readJsonResponseAsMap(connection);
+        assertNull("Unexpected user", response2.get("user"));
+    }
+
+    public void testCramMD5SaslAuthenticationForNonExistingUser() throws Exception
+    {
+        startBrokerNow();
+
+        // request the challenge for CRAM-MD5
+        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5");
+        List cookies = connection.getHeaderFields().get("Set-Cookie");
+
+        // authenticate user with correct credentials
+        int code = authenticateUser(connection, "nonexisting", "admin", "CRAM-MD5");
+        assertEquals("Unexpected response code", 403, code);
+
+        // request authenticated user details
+        connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
+        applyCookiesToConnection(cookies, connection);
+        Map response2 = getRestTestHelper().readJsonResponseAsMap(connection);
+        assertNull("Unexpected user",  response2.get("user"));
+    }
+
+    public void testCramMD5HexSaslAuthenticationForValidCredentials() throws Exception
+    {
+        configureBase64MD5FilePrincipalDatabase();
+        startBrokerNow();
+
+        // request the challenge for CRAM-MD5-HEX
+        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HEX");
+        List cookies = connection.getHeaderFields().get("Set-Cookie");
+
+        // authenticate user with correct credentials
+        int code = authenticateUser(connection, "admin", "admin", "CRAM-MD5-HEX");
+        assertEquals("Unexpected response code", 200, code);
+
+        // request authenticated user details
+        connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
+        applyCookiesToConnection(cookies, connection);
+        Map response2 = getRestTestHelper().readJsonResponseAsMap(connection);
+        assertEquals("Unexpected user", "admin", response2.get("user"));
+    }
+
+    public void testCramMD5HexSaslAuthenticationForIncorrectPassword() throws Exception
+    {
+        configureBase64MD5FilePrincipalDatabase();
+        startBrokerNow();
+
+        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HEX");
+        List cookies = connection.getHeaderFields().get("Set-Cookie");
+
+        // try to authenticate user with incorrect passowrd
+        int code = authenticateUser(connection, "admin", "incorrect", "CRAM-MD5-HEX");
+        assertEquals("Unexpected response code", 403, code);
+
+        // request authenticated user details
+        connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
+        applyCookiesToConnection(cookies, connection);
+        Map response2 = getRestTestHelper().readJsonResponseAsMap(connection);
+        assertNull("Unexpected user", response2.get("user"));
+    }
+
+    public void testCramMD5HexSaslAuthenticationForNonExistingUser() throws Exception
+    {
+        configureBase64MD5FilePrincipalDatabase();
+        startBrokerNow();
+
+        HttpURLConnection connection = requestSasServerChallenge("CRAM-MD5-HEX");
+        List cookies = connection.getHeaderFields().get("Set-Cookie");
+
+        // try to authenticate non-existing user
+        int code = authenticateUser(connection, "nonexisting", "admin", "CRAM-MD5-HEX");
+        assertEquals("Unexpected response code", 403, code);
+
+        // request authenticated user details
+        connection = getRestTestHelper().openManagementConnection("/rest/sasl", "GET");
+        applyCookiesToConnection(cookies, connection);
+        Map response2 = getRestTestHelper().readJsonResponseAsMap(connection);
+        assertNull("Unexpected user", response2.get("user"));
+    }
+
+    private HttpURLConnection requestSasServerChallenge(String mechanism) throws IOException
+    {
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST");
+        OutputStream os = connection.getOutputStream();
+        os.write(("mechanism=" + mechanism).getBytes());
+        os.flush();
+        return connection;
+    }
+
+    private int authenticateUser(HttpURLConnection requestChallengeConnection, String userName, String userPassword, String mechanism)
+            throws IOException, JsonParseException, JsonMappingException, Exception
+    {
+        // get the response
+        Map response = getRestTestHelper().readJsonResponseAsMap(requestChallengeConnection);
+        String challenge = (String) response.get("challenge");
+        assertNotNull("Challenge is not found", challenge);
+
+        // preserve cookies to have the same server session
+        List cookies = requestChallengeConnection.getHeaderFields().get("Set-Cookie");
+
+        // generate the authentication response for the challenge received
+        byte[] challengeBytes = Base64.decodeBase64(challenge);
+        byte[] responseBytes = generateClientResponse(mechanism, userName, userPassword, challengeBytes);
+        String responseData = Base64.encodeBase64String(responseBytes);
+        String requestParameters = ("id=" + response.get("id") + "&response=" + responseData);
+
+        // re-open connection
+        HttpURLConnection authenticateConnection = getRestTestHelper().openManagementConnection("/rest/sasl", "POST");
+
+        // set cookies to use the same server session
+        applyCookiesToConnection(cookies, authenticateConnection);
+        OutputStream os = authenticateConnection.getOutputStream();
+        os.write(requestParameters.getBytes());
+        os.flush();
+        return authenticateConnection.getResponseCode();
+    }
+
+    private byte[] generateClientResponse(String mechanism, String userName, String userPassword, byte[] challengeBytes) throws Exception
+    {
+        byte[] responseBytes =  null;
+        if ("CRAM-MD5-HEX".equalsIgnoreCase(mechanism))
+        {
+            responseBytes = generateCramMD5HexClientResponse(userName, userPassword, challengeBytes);
+        }
+        else if ("CRAM-MD5".equalsIgnoreCase(mechanism))
+        {
+            responseBytes = generateCramMD5ClientResponse(userName, userPassword, challengeBytes);
+        }
+        else
+        {
+            throw new RuntimeException("Not implemented test mechanism " + mechanism);
+        }
+        return responseBytes;
+    }
+
+    private void applyCookiesToConnection(List cookies, HttpURLConnection connection)
+    {
+        for (String cookie : cookies)
+        {
+            connection.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
+        }
+    }
+
+    private static byte SEPARATOR = 0;
+
+    private byte[] generatePlainClientResponse(String userName, String userPassword) throws Exception
+    {
+        byte[] password = userPassword.getBytes("UTF8");
+        byte user[] = userName.getBytes("UTF8");
+        byte response[] = new byte[password.length + user.length + 2 ];
+        int size = 0;
+        response[size++] = SEPARATOR;
+        System.arraycopy(user, 0, response, size, user.length);
+        size += user.length;
+        response[size++] = SEPARATOR;
+        System.arraycopy(password, 0, response, size, password.length);
+        return response;
+    }
+
+    private byte[] generateCramMD5HexClientResponse(String userName, String userPassword, byte[] challengeBytes) throws Exception
+    {
+        String macAlgorithm = "HmacMD5";
+        byte[] digestedPasswordBytes = MessageDigest.getInstance("MD5").digest(userPassword.getBytes("UTF-8"));
+        byte[] hexEncodedDigestedPasswordBytes = toHex(digestedPasswordBytes).getBytes("UTF-8");
+        Mac mac = Mac.getInstance(macAlgorithm);
+        mac.init(new SecretKeySpec(hexEncodedDigestedPasswordBytes, macAlgorithm));
+        final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes);
+        String responseAsString = userName + " " + toHex(messageAuthenticationCode);
+        return responseAsString.getBytes();
+    }
+
+    private byte[] generateCramMD5ClientResponse(String userName, String userPassword, byte[] challengeBytes) throws Exception
+    {
+        String macAlgorithm = "HmacMD5";
+        Mac mac = Mac.getInstance(macAlgorithm);
+        mac.init(new SecretKeySpec(userPassword.getBytes("UTF-8"), macAlgorithm));
+        final byte[] messageAuthenticationCode = mac.doFinal(challengeBytes);
+        String responseAsString = userName + " " + toHex(messageAuthenticationCode);
+        return responseAsString.getBytes();
+    }
+
+    private String toHex(byte[] data)
+    {
+        StringBuffer hash = new StringBuffer();
+        for (int i = 0; i < data.length; i++)
+        {
+            String hex = Integer.toHexString(0xFF & data[i]);
+            if (hex.length() == 1)
+            {
+                hash.append('0');
+            }
+            hash.append(hex);
+        }
+        return hash.toString();
+    }
+
+    private void configureBase64MD5FilePrincipalDatabase() throws IOException, ConfigurationException
+    {
+        // generate user password entry
+        String passwordFileEntry;
+        try
+        {
+            passwordFileEntry = new Passwd().getOutput("admin", "admin");
+        }
+        catch (NoSuchAlgorithmException e)
+        {
+            throw new ConfigurationException(e);
+        }
+
+        // store the entry in the file
+        File passwordFile = File.createTempFile("passwd", "pwd");
+        passwordFile.deleteOnExit();
+
+        FileWriter writer = null;
+        try
+        {
+            writer = new FileWriter(passwordFile);
+            writer.write(passwordFileEntry);
+        }
+        finally
+        {
+            writer.close();
+        }
+
+        // configure broker to use Base64MD5PasswordFilePrincipalDatabase
+        Map newAttributes = new HashMap();
+        newAttributes.put(AbstractPrincipalDatabaseAuthManagerFactory.ATTRIBUTE_PATH, passwordFile.getAbsolutePath());
+        newAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, Base64MD5PasswordFileAuthenticationManagerFactory.PROVIDER_TYPE);
+        getBrokerConfiguration().setObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, newAttributes);
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java
new file mode 100644
index 0000000000..427934fac2
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java
@@ -0,0 +1,114 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.Port;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+
+public class StructureRestTest extends QpidRestTestCase
+{
+
+    public void testGet() throws Exception
+    {
+        Map structure = getRestTestHelper().getJsonAsMap("/rest/structure");
+        assertNotNull("Structure data cannot be null", structure);
+        assertNode(structure, "QpidBroker");
+
+        @SuppressWarnings("unchecked")
+        List> virtualhosts = (List>) structure.get("virtualhosts");
+        assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size());
+
+        @SuppressWarnings("unchecked")
+        List> ports = (List>) structure.get("ports");
+        assertEquals("Unexpected number of ports", 4, ports.size());
+
+        @SuppressWarnings("unchecked")
+        List> providers = (List>) structure.get("authenticationproviders");
+        assertEquals("Unexpected number of authentication providers", 1, providers.size());
+
+        for (String hostName : EXPECTED_VIRTUALHOSTS)
+        {
+            Map host = getRestTestHelper().find("name", hostName, virtualhosts);
+            assertNotNull("Host " + hostName + " is not found ", host);
+            assertNode(host, hostName);
+
+            @SuppressWarnings("unchecked")
+            List> queues = (List>) host.get("queues");
+            assertNotNull("Host " + hostName + " queues are not found ", queues);
+            for (String queueName : EXPECTED_QUEUES)
+            {
+                Map queue = getRestTestHelper().find("name", queueName, queues);
+                assertNotNull(hostName + " queue " + queueName + " is not found ", queue);
+                assertNode(queue, queueName);
+
+                @SuppressWarnings("unchecked")
+                List> bindings = (List>) queue.get("bindings");
+                assertNotNull(hostName + " queue " + queueName + " bindings are not found ", queues);
+                for (Map binding : bindings)
+                {
+                    assertNode(binding, queueName);
+                }
+            }
+
+            @SuppressWarnings("unchecked")
+            List> exchanges = (List>) host.get("exchanges");
+            assertNotNull("Host " + hostName + " exchanges are not found ", exchanges);
+            for (String exchangeName : EXPECTED_EXCHANGES)
+            {
+                Map exchange = getRestTestHelper().find("name", exchangeName, exchanges);
+                assertNotNull("Exchange " + exchangeName + " is not found ", exchange);
+                assertNode(exchange, exchangeName);
+                if ("amq.direct".equalsIgnoreCase(exchangeName) || "<>".equalsIgnoreCase(exchangeName))
+                {
+                    @SuppressWarnings("unchecked")
+                    List> bindings = (List>) exchange.get("bindings");
+                    assertNotNull(hostName + " exchange " + exchangeName + " bindings are not found ", bindings);
+                    for (String queueName : EXPECTED_QUEUES)
+                    {
+                        Map binding = getRestTestHelper().find("name", queueName, bindings);
+                        assertNotNull(hostName + " exchange " + exchangeName + " binding  " + queueName + " is not found", binding);
+                        assertNode(binding, queueName);
+                    }
+                }
+            }
+        }
+
+
+        String httpPortName = TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT;
+        Map portData = getRestTestHelper().find(Port.NAME, httpPortName, ports);
+        assertNotNull("Http Port " + httpPortName + " is not found", portData);
+        assertNode(portData, httpPortName);
+
+        String amqpPortName = TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT;
+        Map amqpPortData = getRestTestHelper().find(Port.NAME, amqpPortName, ports);
+        assertNotNull("Amqp port " + amqpPortName + " is not found", amqpPortData);
+        assertNode(amqpPortData, amqpPortName);
+    }
+
+    private void assertNode(Map node, String name)
+    {
+        assertEquals("Unexpected name", name, node.get("name"));
+        assertNotNull("Unexpected id", node.get("id"));
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java
new file mode 100644
index 0000000000..017467a8be
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/UserRestTest.java
@@ -0,0 +1,99 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.qpid.server.model.User;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+
+public class UserRestTest extends QpidRestTestCase
+{
+    @Override
+    public void setUp() throws Exception
+    {
+        getRestTestHelper().configureTemporaryPasswordFile(this, "user1", "user2");
+
+        super.setUp(); // do this last because it starts the broker, using the modified config
+    }
+
+    public void testGet() throws Exception
+    {
+        List> users = getRestTestHelper().getJsonAsList("/rest/user");
+        assertNotNull("Users cannot be null", users);
+        assertTrue("Unexpected number of users", users.size() > 1);
+        for (Map user : users)
+        {
+            assertUser(user);
+        }
+    }
+
+    public void testGetUserByName() throws Exception
+    {
+        List> users = getRestTestHelper().getJsonAsList("/rest/user");
+        assertNotNull("Users cannot be null", users);
+        assertTrue("Unexpected number of users", users.size() > 1);
+        for (Map user : users)
+        {
+            assertNotNull("Attribute " + User.ID, user.get(User.ID));
+            String userName = (String) user.get(User.NAME);
+            assertNotNull("Attribute " + User.NAME, userName);
+            Map userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/"
+                    + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + userName);
+            assertUser(userDetails);
+            assertEquals("Unexpected user name", userName, userDetails.get(User.NAME));
+        }
+    }
+
+    public void testPut() throws Exception
+    {
+        String userName = getTestName();
+        getRestTestHelper().createOrUpdateUser(userName, "newPassword");
+
+        Map userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/"
+                + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + userName);
+        assertUser(userDetails);
+        assertEquals("Unexpected user name", userName, userDetails.get(User.NAME));
+    }
+
+    public void testDelete() throws Exception
+    {
+        String userName = getTestName();
+        getRestTestHelper().createOrUpdateUser(userName, "newPassword");
+
+        Map userDetails = getRestTestHelper().getJsonAsSingletonList("/rest/user/"
+                + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + userName);
+        String id = (String) userDetails.get(User.ID);
+
+        getRestTestHelper().removeUserById(id);
+
+        List> users = getRestTestHelper().getJsonAsList("/rest/user/"
+                + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + userName);
+        assertEquals("User should be deleted", 0, users.size());
+    }
+
+    private void assertUser(Map user)
+    {
+        assertNotNull("Attribute " + User.ID, user.get(User.ID));
+        assertNotNull("Attribute " + User.NAME, user.get(User.NAME));
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java
new file mode 100644
index 0000000000..fb2c941203
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java
@@ -0,0 +1,576 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jms.Session;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.AMQQueueFactory;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.map.JsonMappingException;
+
+public class VirtualHostRestTest extends QpidRestTestCase
+{
+    private static final String VIRTUALHOST_EXCHANGES_ATTRIBUTE = "exchanges";
+    public static final String VIRTUALHOST_QUEUES_ATTRIBUTE = "queues";
+    public static final String VIRTUALHOST_CONNECTIONS_ATTRIBUTE = "connections";
+
+    private AMQConnection _connection;
+
+    public void testGet() throws Exception
+    {
+        List> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/");
+        assertNotNull("Hosts data cannot be null", hosts);
+        assertEquals("Unexpected number of hosts", EXPECTED_VIRTUALHOSTS.length, hosts.size());
+        for (String hostName : EXPECTED_VIRTUALHOSTS)
+        {
+            Map host = getRestTestHelper().find("name", hostName, hosts);
+            Asserts.assertVirtualHost(hostName, host);
+        }
+    }
+
+    public void testGetHost() throws Exception
+    {
+        // create AMQP connection to get connection JSON details
+        _connection = (AMQConnection) getConnection();
+        _connection.createSession(true, Session.SESSION_TRANSACTED);
+
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+        Asserts.assertVirtualHost("test", hostDetails);
+
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) hostDetails.get(Asserts.STATISTICS_ATTRIBUTE);
+        assertEquals("Unexpected number of exchanges in statistics", EXPECTED_EXCHANGES.length, statistics.get(VirtualHost.EXCHANGE_COUNT));
+        assertEquals("Unexpected number of queues in statistics", EXPECTED_QUEUES.length, statistics.get(VirtualHost.QUEUE_COUNT));
+        assertEquals("Unexpected number of connections in statistics", 1, statistics.get(VirtualHost.CONNECTION_COUNT));
+
+        @SuppressWarnings("unchecked")
+        List> exchanges = (List>) hostDetails.get(VIRTUALHOST_EXCHANGES_ATTRIBUTE);
+        assertEquals("Unexpected number of exchanges", EXPECTED_EXCHANGES.length, exchanges.size());
+        Asserts.assertDurableExchange("amq.fanout", "fanout", getRestTestHelper().find(Exchange.NAME, "amq.fanout", exchanges));
+        Asserts.assertDurableExchange("amq.topic", "topic", getRestTestHelper().find(Exchange.NAME, "amq.topic", exchanges));
+        Asserts.assertDurableExchange("amq.direct", "direct", getRestTestHelper().find(Exchange.NAME, "amq.direct", exchanges));
+        Asserts.assertDurableExchange("amq.match", "headers", getRestTestHelper().find(Exchange.NAME, "amq.match", exchanges));
+        Asserts.assertDurableExchange("<>", "direct", getRestTestHelper().find(Exchange.NAME, "<>", exchanges));
+
+        @SuppressWarnings("unchecked")
+        List> queues = (List>) hostDetails.get(VIRTUALHOST_QUEUES_ATTRIBUTE);
+        assertEquals("Unexpected number of queues", EXPECTED_QUEUES.length, queues.size());
+        Map queue = getRestTestHelper().find(Queue.NAME,  "queue", queues);
+        Map ping = getRestTestHelper().find(Queue.NAME, "ping", queues);
+        Asserts.assertQueue("queue", "standard", queue);
+        Asserts.assertQueue("ping", "standard", ping);
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, queue.get(Queue.DURABLE));
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.FALSE, ping.get(Queue.DURABLE));
+
+        @SuppressWarnings("unchecked")
+        List> connections = (List>) hostDetails
+                .get(VIRTUALHOST_CONNECTIONS_ATTRIBUTE);
+        assertEquals("Unexpected number of connections", 1, connections.size());
+        Asserts.assertConnection(connections.get(0), _connection);
+    }
+
+    public void testPutCreateVirtualHostUsingStoreType() throws Exception
+    {
+        String hostName = getTestName();
+        String storeType = getTestProfileMessageStoreType();
+        String storeLocation = createHost(hostName, storeType, null);
+        try
+        {
+            // make sure that the host is saved in the broker store
+            restartBroker();
+            Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostName);
+            Asserts.assertVirtualHost(hostName, hostDetails);
+            assertEquals("Unexpected store type", storeType, hostDetails.get(VirtualHost.STORE_TYPE));
+
+            assertNewVirtualHost(hostDetails);
+        }
+        finally
+        {
+            if (storeLocation != null)
+            {
+                FileUtils.delete(new File(storeLocation), true);
+            }
+        }
+    }
+
+    public void testPutCreateVirtualHostUsingConfigPath() throws Exception
+    {
+        String hostName = getTestName();
+        File configFile = TestFileUtils.createTempFile(this, hostName + "-config.xml");
+        String configPath = configFile.getAbsolutePath();
+        String storeLocation = getStoreLocation(hostName);
+        createAndSaveVirtualHostConfiguration(hostName, configFile, storeLocation);
+        createHost(hostName, null, configPath);
+        try
+        {
+            // make sure that the host is saved in the broker store
+            restartBroker();
+            Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostName);
+            Asserts.assertVirtualHost(hostName, hostDetails);
+            assertEquals("Unexpected config path", configPath, hostDetails.get(VirtualHost.CONFIG_PATH));
+
+            assertNewVirtualHost(hostDetails);
+        }
+        finally
+        {
+            if (storeLocation != null)
+            {
+                FileUtils.delete(new File(storeLocation), true);
+            }
+            configFile.delete();
+        }
+    }
+
+    public void testDeleteHost() throws Exception
+    {
+        String hostToDelete = TEST3_VIRTUALHOST;
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/virtualhost/" + hostToDelete, "DELETE");
+        connection.connect();
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+
+        // make sure that changes are saved in the broker store
+        restartBroker();
+
+        List> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/" + hostToDelete);
+        assertEquals("Host should be deleted", 0, hosts.size());
+    }
+
+    public void testPutCreateQueue() throws Exception
+    {
+        String queueName = getTestQueueName();
+
+        createQueue(queueName + "-standard", "standard", null);
+
+        Map sortedQueueAttributes = new HashMap();
+        sortedQueueAttributes.put(Queue.SORT_KEY, "sortme");
+        createQueue(queueName + "-sorted", "sorted", sortedQueueAttributes);
+
+        Map priorityQueueAttributes = new HashMap();
+        priorityQueueAttributes.put(Queue.PRIORITIES, 10);
+        createQueue(queueName + "-priority", "priority", priorityQueueAttributes);
+
+        Map lvqQueueAttributes = new HashMap();
+        lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ");
+        createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes);
+
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+
+        @SuppressWarnings("unchecked")
+        List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+        Map standardQueue = getRestTestHelper().find(Queue.NAME, queueName + "-standard" , queues);
+        Map sortedQueue = getRestTestHelper().find(Queue.NAME, queueName + "-sorted" , queues);
+        Map priorityQueue = getRestTestHelper().find(Queue.NAME, queueName + "-priority" , queues);
+        Map lvqQueue = getRestTestHelper().find(Queue.NAME, queueName + "-lvq" , queues);
+
+        Asserts.assertQueue(queueName + "-standard", "standard", standardQueue);
+        Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue);
+        Asserts.assertQueue(queueName + "-priority", "priority", priorityQueue);
+        Asserts.assertQueue(queueName + "-lvq", "lvq", lvqQueue);
+
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, standardQueue.get(Queue.DURABLE));
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, sortedQueue.get(Queue.DURABLE));
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE));
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE));
+
+        assertEquals("Unexpected sorted key attribute", "sortme", sortedQueue.get(Queue.SORT_KEY));
+        assertEquals("Unexpected lvq key attribute", "LVQ", lvqQueue.get(Queue.LVQ_KEY));
+        assertEquals("Unexpected priorities key attribute", 10, priorityQueue.get(Queue.PRIORITIES));
+    }
+
+    public void testPutCreateExchange() throws Exception
+    {
+        String exchangeName = getTestName();
+
+        createExchange(exchangeName + "-direct", "direct");
+        createExchange(exchangeName + "-topic", "topic");
+        createExchange(exchangeName + "-headers", "headers");
+        createExchange(exchangeName + "-fanout", "fanout");
+
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+
+        @SuppressWarnings("unchecked")
+        List> exchanges = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE);
+        Map directExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-direct" , exchanges);
+        Map topicExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-topic" , exchanges);
+        Map headersExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-headers" , exchanges);
+        Map fanoutExchange = getRestTestHelper().find(Queue.NAME, exchangeName + "-fanout" , exchanges);
+
+        Asserts.assertDurableExchange(exchangeName + "-direct", "direct", directExchange);
+        Asserts.assertDurableExchange(exchangeName + "-topic", "topic", topicExchange);
+        Asserts.assertDurableExchange(exchangeName + "-headers", "headers", headersExchange);
+        Asserts.assertDurableExchange(exchangeName + "-fanout", "fanout", fanoutExchange);
+
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, directExchange.get(Queue.DURABLE));
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, topicExchange.get(Queue.DURABLE));
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, headersExchange.get(Queue.DURABLE));
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, fanoutExchange.get(Queue.DURABLE));
+
+    }
+
+    public void testPutCreateLVQWithoutKey() throws Exception
+    {
+        String queueName = getTestQueueName()+ "-lvq";
+        createQueue(queueName, "lvq", null);
+
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+
+        @SuppressWarnings("unchecked")
+        List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+        Map lvqQueue = getRestTestHelper().find(Queue.NAME, queueName  , queues);
+
+        Asserts.assertQueue(queueName , "lvq", lvqQueue);
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE));
+        assertEquals("Unexpected lvq key attribute", AMQQueueFactory.QPID_LVQ_KEY, lvqQueue.get(Queue.LVQ_KEY));
+    }
+
+    public void testPutCreateSortedQueueWithoutKey() throws Exception
+    {
+        String queueName = getTestQueueName() + "-sorted";
+        int responseCode = tryCreateQueue(queueName, "sorted", null);
+        assertEquals("Unexpected response code", HttpServletResponse.SC_CONFLICT, responseCode);
+
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+
+        @SuppressWarnings("unchecked")
+        List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+        Map testQueue = getRestTestHelper().find(Queue.NAME, queueName  , queues);
+
+        assertNull("Sorted queue without a key was created ", testQueue);
+    }
+
+    public void testPutCreatePriorityQueueWithoutKey() throws Exception
+    {
+        String queueName = getTestQueueName()+ "-priority";
+        createQueue(queueName, "priority", null);
+
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+
+        @SuppressWarnings("unchecked")
+        List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+        Map priorityQueue = getRestTestHelper().find(Queue.NAME, queueName  , queues);
+
+        Asserts.assertQueue(queueName , "priority", priorityQueue);
+        assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, priorityQueue.get(Queue.DURABLE));
+        assertEquals("Unexpected number of priorities", 10, priorityQueue.get(Queue.PRIORITIES));
+    }
+
+    public void testPutCreateStandardQueueWithoutType() throws Exception
+    {
+        String queueName = getTestQueueName();
+        createQueue(queueName, null, null);
+
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+
+        @SuppressWarnings("unchecked")
+        List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+        Map queue = getRestTestHelper().find(Queue.NAME, queueName  , queues);
+
+        Asserts.assertQueue(queueName , "standard", queue);
+    }
+
+    public void testPutCreateQueueOfUnsupportedType() throws Exception
+    {
+        String queueName = getTestQueueName();
+        int responseCode = tryCreateQueue(queueName, "unsupported", null);
+        assertEquals("Unexpected response code", HttpServletResponse.SC_CONFLICT, responseCode);
+
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+
+        @SuppressWarnings("unchecked")
+        List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+        Map queue = getRestTestHelper().find(Queue.NAME, queueName  , queues);
+
+        assertNull("Queue of unsupported type was created", queue);
+    }
+
+    public void testDeleteQueue() throws Exception
+    {
+        String queueName = getTestQueueName();
+        createQueue(queueName, null, null);
+
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "DELETE");
+        connection.connect();
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+        List> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName);
+        assertEquals("Queue should be deleted", 0, queues.size());
+    }
+
+    public void testDeleteQueueById() throws Exception
+    {
+        String queueName = getTestQueueName();
+        createQueue(queueName, null, null);
+        Map queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName);
+
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE");
+        connection.connect();
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+        List> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName);
+        assertEquals("Queue should be deleted", 0, queues.size());
+    }
+
+    public void testDeleteExchange() throws Exception
+    {
+        String exchangeName = getTestName();
+        createExchange(exchangeName, "direct");
+
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "DELETE");
+        connection.connect();
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+        List> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName);
+        assertEquals("Exchange should be deleted", 0, queues.size());
+    }
+
+    public void testDeleteExchangeById() throws Exception
+    {
+        String exchangeName = getTestName();
+        createExchange(exchangeName, "direct");
+        Map echangeDetails = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + exchangeName);
+
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE");
+        connection.connect();
+        assertEquals("Unexpected response code", 200, connection.getResponseCode());
+        List> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName);
+        assertEquals("Exchange should be deleted", 0, queues.size());
+    }
+
+    public void testPutCreateQueueWithAttributes() throws Exception
+    {
+        String queueName = getTestQueueName();
+
+        Map attributes = new HashMap();
+        attributes.put(Queue.ALERT_REPEAT_GAP, 1000);
+        attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, 3600000);
+        attributes.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, 1000000000);
+        attributes.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 800);
+        attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 15);
+        attributes.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 2000000000);
+        attributes.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 1500000000);
+
+        createQueue(queueName + "-standard", "standard", attributes);
+
+        Map sortedQueueAttributes = new HashMap();
+        sortedQueueAttributes.putAll(attributes);
+        sortedQueueAttributes.put(Queue.SORT_KEY, "sortme");
+        createQueue(queueName + "-sorted", "sorted", sortedQueueAttributes);
+
+        Map priorityQueueAttributes = new HashMap();
+        priorityQueueAttributes.putAll(attributes);
+        priorityQueueAttributes.put(Queue.PRIORITIES, 10);
+        createQueue(queueName + "-priority", "priority", priorityQueueAttributes);
+
+        Map lvqQueueAttributes = new HashMap();
+        lvqQueueAttributes.putAll(attributes);
+        lvqQueueAttributes.put(Queue.LVQ_KEY, "LVQ");
+        createQueue(queueName + "-lvq", "lvq", lvqQueueAttributes);
+
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+
+        @SuppressWarnings("unchecked")
+        List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+        Map standardQueue = getRestTestHelper().find(Queue.NAME, queueName + "-standard" , queues);
+        Map sortedQueue = getRestTestHelper().find(Queue.NAME, queueName + "-sorted" , queues);
+        Map priorityQueue = getRestTestHelper().find(Queue.NAME, queueName + "-priority" , queues);
+        Map lvqQueue = getRestTestHelper().find(Queue.NAME, queueName + "-lvq" , queues);
+
+        attributes.put(Queue.DURABLE, Boolean.TRUE);
+        Asserts.assertQueue(queueName + "-standard", "standard", standardQueue, attributes);
+        Asserts.assertQueue(queueName + "-sorted", "sorted", sortedQueue, attributes);
+        Asserts.assertQueue(queueName + "-priority", "priority", priorityQueue, attributes);
+        Asserts.assertQueue(queueName + "-lvq", "lvq", lvqQueue, attributes);
+
+        assertEquals("Unexpected sorted key attribute", "sortme", sortedQueue.get(Queue.SORT_KEY));
+        assertEquals("Unexpected lvq key attribute", "LVQ", lvqQueue.get(Queue.LVQ_KEY));
+        assertEquals("Unexpected priorities key attribute", 10, priorityQueue.get(Queue.PRIORITIES));
+    }
+
+    @SuppressWarnings("unchecked")
+    public void testCreateQueueWithDLQEnabled() throws Exception
+    {
+        String queueName = getTestQueueName();
+
+        Map attributes = new HashMap();
+        attributes.put(AMQQueueFactory.X_QPID_DLQ_ENABLED, true);
+
+        //verify the starting state
+        Map hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+        List> queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+        List> exchanges = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE);
+
+        assertNull("queue should not have already been present", getRestTestHelper().find(Queue.NAME, queueName , queues));
+        assertNull("queue should not have already been present", getRestTestHelper().find(Queue.NAME, queueName + "_DLQ" , queues));
+        assertNull("exchange should not have already been present", getRestTestHelper().find(Exchange.NAME, queueName + "_DLE" , exchanges));
+
+        //create the queue
+        createQueue(queueName, "standard", attributes);
+
+        //verify the new queue, as well as the DLQueue and DLExchange have been created
+        hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test");
+        queues = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_QUEUES_ATTRIBUTE);
+        exchanges = (List>) hostDetails.get(VirtualHostRestTest.VIRTUALHOST_EXCHANGES_ATTRIBUTE);
+
+        Map queue = getRestTestHelper().find(Queue.NAME, queueName , queues);
+        Map dlqQueue = getRestTestHelper().find(Queue.NAME, queueName + "_DLQ" , queues);
+        Map dlExchange = getRestTestHelper().find(Exchange.NAME, queueName + "_DLE" , exchanges);
+        assertNotNull("queue should not have been present", queue);
+        assertNotNull("queue should not have been present", dlqQueue);
+        assertNotNull("exchange should not have been present", dlExchange);
+
+        //verify that the alternate exchange is set as expected on the new queue
+        Map queueAttributes = new HashMap();
+        queueAttributes.put(Queue.ALTERNATE_EXCHANGE, queueName + "_DLE");
+
+        Asserts.assertQueue(queueName, "standard", queue, queueAttributes);
+        Asserts.assertQueue(queueName, "standard", queue, null);
+    }
+
+    private void createExchange(String exchangeName, String exchangeType) throws IOException
+    {
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "PUT");
+
+        Map queueData = new HashMap();
+        queueData.put(Exchange.NAME, exchangeName);
+        queueData.put(Exchange.DURABLE, Boolean.TRUE);
+        queueData.put(Exchange.TYPE, exchangeType);
+
+        getRestTestHelper().writeJsonRequest(connection, queueData);
+        assertEquals("Unexpected response code", 201, connection.getResponseCode());
+
+        connection.disconnect();
+    }
+
+    private void createQueue(String queueName, String queueType, Map attributes) throws IOException,
+            JsonGenerationException, JsonMappingException
+    {
+        int responseCode = tryCreateQueue(queueName, queueType, attributes);
+        assertEquals("Unexpected response code", 201, responseCode);
+    }
+
+    private int tryCreateQueue(String queueName, String queueType, Map attributes) throws IOException,
+            JsonGenerationException, JsonMappingException
+    {
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "PUT");
+
+        Map queueData = new HashMap();
+        queueData.put(Queue.NAME, queueName);
+        queueData.put(Queue.DURABLE, Boolean.TRUE);
+        if (queueType != null)
+        {
+            queueData.put(Queue.TYPE, queueType);
+        }
+        if (attributes != null)
+        {
+            queueData.putAll(attributes);
+        }
+
+        getRestTestHelper().writeJsonRequest(connection, queueData);
+        int responseCode = connection.getResponseCode();
+        connection.disconnect();
+        return responseCode;
+    }
+
+    private String createHost(String hostName, String storeType, String configPath) throws IOException, JsonGenerationException,
+            JsonMappingException
+    {
+        String storePath = getStoreLocation(hostName);
+        int responseCode = tryCreateVirtualHost(hostName, storeType, storePath, configPath);
+        assertEquals("Unexpected response code", 201, responseCode);
+        return storePath;
+    }
+
+    private String getStoreLocation(String hostName)
+    {
+        return new File(TMP_FOLDER, "store-" + hostName + "-" + System.currentTimeMillis()).getAbsolutePath();
+    }
+
+    private int tryCreateVirtualHost(String hostName, String storeType, String storePath, String configPath) throws IOException,
+            JsonGenerationException, JsonMappingException
+    {
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/virtualhost/" + hostName, "PUT");
+
+        Map hostData = new HashMap();
+        hostData.put(VirtualHost.NAME, hostName);
+        if (storeType == null)
+        {
+            hostData.put(VirtualHost.CONFIG_PATH, configPath);
+        }
+        else
+        {
+            hostData.put(VirtualHost.STORE_PATH, storePath);
+            hostData.put(VirtualHost.STORE_TYPE, storeType);
+        }
+
+        getRestTestHelper().writeJsonRequest(connection, hostData);
+        int responseCode = connection.getResponseCode();
+        connection.disconnect();
+        return responseCode;
+    }
+
+    private XMLConfiguration createAndSaveVirtualHostConfiguration(String hostName, File configFile, String storeLocation)
+            throws ConfigurationException
+    {
+        XMLConfiguration testConfiguration = new XMLConfiguration();
+        testConfiguration.setProperty("virtualhosts.virtualhost." + hostName + ".store.class",
+                getTestProfileMessageStoreClassName());
+        testConfiguration.setProperty("virtualhosts.virtualhost." + hostName + ".store.environment-path", storeLocation);
+        testConfiguration.save(configFile);
+        return testConfiguration;
+    }
+
+    private void assertNewVirtualHost(Map hostDetails)
+    {
+        @SuppressWarnings("unchecked")
+        Map statistics = (Map) hostDetails.get(Asserts.STATISTICS_ATTRIBUTE);
+        assertEquals("Unexpected number of exchanges in statistics", EXPECTED_EXCHANGES.length,
+                statistics.get(VirtualHost.EXCHANGE_COUNT));
+        assertEquals("Unexpected number of queues in statistics", 0, statistics.get(VirtualHost.QUEUE_COUNT));
+        assertEquals("Unexpected number of connections in statistics", 0, statistics.get(VirtualHost.CONNECTION_COUNT));
+
+        @SuppressWarnings("unchecked")
+        List> exchanges = (List>) hostDetails.get(VIRTUALHOST_EXCHANGES_ATTRIBUTE);
+        assertEquals("Unexpected number of exchanges", EXPECTED_EXCHANGES.length, exchanges.size());
+        RestTestHelper restTestHelper = getRestTestHelper();
+        Asserts.assertDurableExchange("amq.fanout", "fanout", restTestHelper.find(Exchange.NAME, "amq.fanout", exchanges));
+        Asserts.assertDurableExchange("amq.topic", "topic", restTestHelper.find(Exchange.NAME, "amq.topic", exchanges));
+        Asserts.assertDurableExchange("amq.direct", "direct", restTestHelper.find(Exchange.NAME, "amq.direct", exchanges));
+        Asserts.assertDurableExchange("amq.match", "headers", restTestHelper.find(Exchange.NAME, "amq.match", exchanges));
+        Asserts.assertDurableExchange("<>", "direct", restTestHelper.find(Exchange.NAME, "<>", exchanges));
+
+        assertNull("Unexpected queues", hostDetails.get(VIRTUALHOST_QUEUES_ATTRIBUTE));
+        assertNull("Unexpected connections", hostDetails.get(VIRTUALHOST_CONNECTIONS_ATTRIBUTE));
+    }
+
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java
new file mode 100644
index 0000000000..40ea723b1e
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java
@@ -0,0 +1,197 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.systest.rest.acl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.security.acl.AbstractACLTestCase;
+import org.apache.qpid.systest.rest.QpidRestTestCase;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+
+public class GroupRestACLTest extends QpidRestTestCase
+{
+    private static final String FILE_GROUP_MANAGER = "FileGroupManager";
+
+    private static final String ALLOWED_GROUP = "allowedGroup";
+    private static final String DENIED_GROUP = "deniedGroup";
+    private static final String OTHER_GROUP = "otherGroup";
+
+    private static final String ALLOWED_USER = "webadmin";
+    private static final String DENIED_USER = "admin";
+    private static final String OTHER_USER = "admin";
+
+    private File _groupFile;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        _groupFile = createTemporaryGroupFile();
+        getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath());
+
+        //DONT call super.setUp(), the tests will start the broker after configuring it
+    }
+
+    @Override
+    protected void customizeConfiguration() throws ConfigurationException, IOException
+    {
+        super.customizeConfiguration();
+        getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpBasicAuthenticationEnabled", true);
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        super.tearDown();
+
+        if (_groupFile != null)
+        {
+            if (_groupFile.exists())
+            {
+                _groupFile.delete();
+            }
+        }
+    }
+
+    private File createTemporaryGroupFile() throws Exception
+    {
+        File groupFile = File.createTempFile("group", "grp");
+        groupFile.deleteOnExit();
+
+        Properties props = new Properties();
+        props.put(ALLOWED_GROUP + ".users", ALLOWED_USER);
+        props.put(DENIED_GROUP + ".users", DENIED_USER);
+        props.put(OTHER_GROUP + ".users", OTHER_USER);
+
+        props.store(new FileOutputStream(groupFile), "test group file");
+
+        return groupFile;
+    }
+
+    public void testCreateGroup() throws Exception
+    {
+        AbstractACLTestCase.writeACLFileUtil(this, null,
+                "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+                "ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE GROUP",
+                "ACL DENY-LOG " + DENIED_GROUP + " CREATE GROUP");
+
+        //Start the broker with the custom config
+        super.setUp();
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+        Map data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        getRestTestHelper().assertNumberOfGroups(data, 3);
+
+        getRestTestHelper().createGroup("newGroup", FILE_GROUP_MANAGER);
+
+        data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        getRestTestHelper().assertNumberOfGroups(data, 4);
+
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+        getRestTestHelper().createGroup("anotherNewGroup", FILE_GROUP_MANAGER, HttpServletResponse.SC_FORBIDDEN);
+
+        data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        getRestTestHelper().assertNumberOfGroups(data, 4);
+    }
+
+    public void testDeleteGroup() throws Exception
+    {
+        AbstractACLTestCase.writeACLFileUtil(this, null,
+                "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+                "ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE GROUP",
+                "ACL DENY-LOG " + DENIED_GROUP + " DELETE GROUP");
+
+        //Start the broker with the custom config
+        super.setUp();
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+        Map data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        getRestTestHelper().assertNumberOfGroups(data, 3);
+
+        getRestTestHelper().removeGroup(OTHER_GROUP, FILE_GROUP_MANAGER, HttpServletResponse.SC_FORBIDDEN);
+
+        data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        getRestTestHelper().assertNumberOfGroups(data, 3);
+
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+
+        getRestTestHelper().removeGroup(OTHER_GROUP, FILE_GROUP_MANAGER);
+
+        data = getRestTestHelper().getJsonAsSingletonList("/rest/groupprovider/" + FILE_GROUP_MANAGER);
+        getRestTestHelper().assertNumberOfGroups(data, 2);
+    }
+
+    public void testUpdateGroupAddMember() throws Exception
+    {
+        AbstractACLTestCase.writeACLFileUtil(this, null,
+                "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+                "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP",
+                "ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP");
+
+        //Start the broker with the custom config
+        super.setUp();
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+        assertNumberOfGroupMembers(OTHER_GROUP, 1);
+
+        getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, OTHER_GROUP, "newGroupMember", HttpServletResponse.SC_FORBIDDEN);
+        assertNumberOfGroupMembers(OTHER_GROUP, 1);
+
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+        getRestTestHelper().createNewGroupMember(FILE_GROUP_MANAGER, OTHER_GROUP, "newGroupMember");
+        assertNumberOfGroupMembers(OTHER_GROUP, 2);
+    }
+
+    public void testUpdateGroupDeleteMember() throws Exception
+    {
+        AbstractACLTestCase.writeACLFileUtil(this, null,
+                "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+                "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP",
+                "ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP");
+
+        //Start the broker with the custom config
+        super.setUp();
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+        assertNumberOfGroupMembers(OTHER_GROUP, 1);
+
+        getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, OTHER_GROUP, OTHER_USER, HttpServletResponse.SC_FORBIDDEN);
+        assertNumberOfGroupMembers(OTHER_GROUP, 1);
+
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+        getRestTestHelper().removeMemberFromGroup(FILE_GROUP_MANAGER, OTHER_GROUP, OTHER_USER);
+        assertNumberOfGroupMembers(OTHER_GROUP, 0);
+    }
+
+    private void assertNumberOfGroupMembers(String groupName, int expectedNumberOfMembers) throws IOException
+    {
+        Map group = getRestTestHelper().getJsonAsSingletonList("/rest/group/FileGroupManager/" + groupName);
+        getRestTestHelper().assertNumberOfGroupMembers(group, expectedNumberOfMembers);
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java
new file mode 100644
index 0000000000..12973113d8
--- /dev/null
+++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpid.systest.rest.acl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.security.acl.AbstractACLTestCase;
+import org.apache.qpid.systest.rest.QpidRestTestCase;
+import org.apache.qpid.test.utils.TestBrokerConfiguration;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+
+public class UserRestACLTest extends QpidRestTestCase
+{
+    private static final String ALLOWED_GROUP = "allowedGroup";
+    private static final String DENIED_GROUP = "deniedGroup";
+    private static final String OTHER_GROUP = "otherGroup";
+
+    private static final String ALLOWED_USER = "webadmin";
+    private static final String DENIED_USER = "admin";
+    private static final String OTHER_USER = "other";
+
+    private File _groupFile;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        _groupFile = createTemporaryGroupFile();
+        getBrokerConfiguration().setBrokerAttribute(Broker.GROUP_FILE, _groupFile.getAbsolutePath());
+
+        getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER, OTHER_USER);
+
+        //DONT call super.setUp(), the tests will start the broker after configuring it
+    }
+
+    @Override
+    protected void customizeConfiguration() throws ConfigurationException, IOException
+    {
+        super.customizeConfiguration();
+        getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, "httpBasicAuthenticationEnabled", true);
+    }
+
+    @Override
+    public void tearDown() throws Exception
+    {
+        super.tearDown();
+
+        if (_groupFile != null)
+        {
+            if (_groupFile.exists())
+            {
+                _groupFile.delete();
+            }
+        }
+    }
+
+    private File createTemporaryGroupFile() throws Exception
+    {
+        File groupFile = File.createTempFile("group", "grp");
+        groupFile.deleteOnExit();
+
+        Properties props = new Properties();
+        props.put(ALLOWED_GROUP + ".users", ALLOWED_USER);
+        props.put(DENIED_GROUP + ".users", DENIED_USER);
+        props.put(OTHER_GROUP + ".users", OTHER_USER);
+
+        props.store(new FileOutputStream(groupFile), "test group file");
+
+        return groupFile;
+    }
+
+    public void testAddUser() throws Exception
+    {
+        AbstractACLTestCase.writeACLFileUtil(this, null,
+                "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+                "ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE USER",
+                "ACL DENY-LOG " + DENIED_GROUP + " CREATE USER");
+
+        //Start the broker with the custom config
+        super.setUp();
+
+        String newUser = "newUser";
+        String password = "password";
+
+        assertUserDoesNotExist(newUser);
+
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+
+        getRestTestHelper().createOrUpdateUser(newUser, password, HttpServletResponse.SC_FORBIDDEN);
+        assertUserDoesNotExist(newUser);
+
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+        getRestTestHelper().createOrUpdateUser(newUser, password);
+        assertUserExists(newUser);
+    }
+
+    public void testDeleteUser() throws Exception
+    {
+        AbstractACLTestCase.writeACLFileUtil(this, null,
+                "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+                "ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE USER",
+                "ACL DENY-LOG " + DENIED_GROUP + " DELETE USER");
+
+        //Start the broker with the custom config
+        super.setUp();
+
+        assertUserExists(OTHER_USER);
+
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+        getRestTestHelper().removeUser(OTHER_USER, HttpServletResponse.SC_FORBIDDEN);
+        assertUserExists(OTHER_USER);
+
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+        getRestTestHelper().removeUser(OTHER_USER);
+        assertUserDoesNotExist(OTHER_USER);
+    }
+
+    public void testUpdateUser() throws Exception
+    {
+        AbstractACLTestCase.writeACLFileUtil(this, null,
+                "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+                "ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE USER",
+                "ACL DENY-LOG " + DENIED_GROUP + " UPDATE USER");
+
+        //Start the broker with the custom config
+        super.setUp();
+
+        String newPassword = "newPassword";
+
+        checkPassword(OTHER_USER, OTHER_USER, true);
+
+        getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER);
+        getRestTestHelper().createOrUpdateUser(OTHER_USER, newPassword, HttpServletResponse.SC_FORBIDDEN);
+
+        checkPassword(OTHER_USER, newPassword, false);
+
+        getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER);
+        getRestTestHelper().createOrUpdateUser(OTHER_USER, newPassword, HttpServletResponse.SC_OK); // expect SC_OK rather than the default SC_CREATED
+
+        checkPassword(OTHER_USER, newPassword, true);
+        checkPassword(OTHER_USER, OTHER_USER, false);
+    }
+
+    private void checkPassword(String username, String password, boolean passwordExpectedToBeCorrect) throws IOException
+    {
+        getRestTestHelper().setUsernameAndPassword(username, password);
+        HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/user/"
+                + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/", "GET");
+
+        boolean passwordIsCorrect = connection.getResponseCode() == HttpServletResponse.SC_OK;
+
+        connection.disconnect();
+
+        assertEquals(passwordExpectedToBeCorrect, passwordIsCorrect);
+    }
+
+    private void assertUserDoesNotExist(String newUser) throws JsonParseException, JsonMappingException, IOException
+    {
+        String path = "/rest/user/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + newUser;
+        List> userDetailsList = getRestTestHelper().getJsonAsList(path);
+        assertTrue(userDetailsList.isEmpty());
+    }
+
+    private void assertUserExists(String username) throws IOException
+    {
+        String path = "/rest/user/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + username;
+        Map userDetails = getRestTestHelper().getJsonAsSingletonList(path);
+
+        assertEquals(
+                "User returned by " + path + " should have name=" + username + ". The returned JSON was: " + userDetails,
+                username,
+                userDetails.get("name"));
+    }
+}
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java
index a53c3d3ee0..2ed3f356d3 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/RollbackOrderTest.java
@@ -40,19 +40,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
  * Description:
  *
  * The problem that this test is exposing is that the dispatcher used to be capable
- * of holding on to a message when stopped. This ment that when the rollback was
+ * of holding on to a message when stopped. This meant that when the rollback was
  * called and the dispatcher stopped it may have hold of a message. So after all
  * the local queues(preDeliveryQueue, SynchronousQueue, PostDeliveryTagQueue)
  * have been cleared the client still had a single message, the one the
  * dispatcher was holding on to.
  *
  * As a result the TxRollback operation would run and then release the dispatcher.
- * Whilst the dispatcher would then proceed to reject the message it was holiding
+ * Whilst the dispatcher would then proceed to reject the message it was holding
  * the Broker would already have resent that message so the rejection would silently
  * fail.
  *
- * And the client would receieve that single message 'early', depending on the
- * number of messages already recevied when rollback was called.
+ * And the client would receive that single message 'early', depending on the
+ * number of messages already received when rollback was called.
  *
  *
  * Aims:
@@ -78,7 +78,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
  * as expected.
  *
  * We are testing a race condition here but we can check through the log file if
- * the race condition occured. However, performing that check will only validate
+ * the race condition occurred. However, performing that check will only validate
  * the problem exists and will not be suitable as part of a system test.
  *
  */
@@ -183,18 +183,8 @@ public class RollbackOrderTest extends QpidBrokerTestCase
             }
         }
 
-//        _consumer.close();
         _connection.close();
         
         assertFalse("Exceptions thrown during test run, Check Std.err.", failed.get());
     }
-
-    @Override public void tearDown() throws Exception
-    {
-
-        drainQueue(_queue);
-
-        super.tearDown();
-    }
-
 }
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java
index e1f93b975b..22a98b6f42 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java
@@ -29,8 +29,6 @@ import org.apache.qpid.client.AMQDestination;
 import org.apache.qpid.client.AMQSession;
 import org.apache.qpid.client.AMQSession_0_10;
 import org.apache.qpid.client.message.QpidMessageProperties;
-import org.apache.qpid.client.messaging.address.Node.ExchangeNode;
-import org.apache.qpid.client.messaging.address.Node.QueueNode;
 import org.apache.qpid.jndi.PropertiesFileInitialContextFactory;
 import org.apache.qpid.messaging.Address;
 import org.apache.qpid.test.utils.QpidBrokerTestCase;
@@ -98,7 +96,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         }
             
         assertFalse("Queue should not be created",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest, (QueueNode)dest.getSourceNode() ,true));
+                (AMQSession_0_10)jmsSession).isQueueExist(dest,false));
         
         
         // create always -------------------------------------------
@@ -107,10 +105,10 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         cons = jmsSession.createConsumer(dest); 
         
         assertTrue("Queue not created as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));              
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, true));
         assertTrue("Queue not bound as expected",(
                 (AMQSession_0_10)jmsSession).isQueueBound("", 
-                    dest.getAddressName(),dest.getAddressName(), dest.getSourceNode().getDeclareArgs()));
+                    dest.getAddressName(),dest.getAddressName(), dest.getNode().getDeclareArgs()));
         
         // create receiver -----------------------------------------
         addr1 = "ADDR:testQueue2; { create: receiver }";
@@ -126,16 +124,16 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         }
             
         assertFalse("Queue should not be created",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, false));
         
         
         cons = jmsSession.createConsumer(dest); 
         
         assertTrue("Queue not created as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));              
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, true));
         assertTrue("Queue not bound as expected",(
                 (AMQSession_0_10)jmsSession).isQueueBound("", 
-                    dest.getAddressName(),dest.getAddressName(), dest.getSourceNode().getDeclareArgs()));
+                    dest.getAddressName(),dest.getAddressName(), dest.getNode().getDeclareArgs()));
         
         // create never --------------------------------------------
         addr1 = "ADDR:testQueue3; { create: never }";
@@ -161,7 +159,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         }
             
         assertFalse("Queue should not be created",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, false));
         
         // create sender ------------------------------------------
         addr1 = "ADDR:testQueue3; { create: sender }";
@@ -177,14 +175,14 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
                     "doesn't resolve to an exchange or a queue"));
         }
         assertFalse("Queue should not be created",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, false));
         
         prod = jmsSession.createProducer(dest);
         assertTrue("Queue not created as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));              
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, true));
         assertTrue("Queue not bound as expected",(
                 (AMQSession_0_10)jmsSession).isQueueBound("", 
-                    dest.getAddressName(),dest.getAddressName(), dest.getSourceNode().getDeclareArgs()));
+                    dest.getAddressName(),dest.getAddressName(), dest.getNode().getDeclareArgs()));
         
     }
  
@@ -221,7 +219,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         // Even if the consumer is closed the queue and the bindings should be intact.
         
         assertTrue("Queue not created as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));              
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, true));
         
         assertTrue("Queue not bound as expected",(
                 (AMQSession_0_10)jmsSession).isQueueBound("", 
@@ -326,7 +324,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         }
         
         assertTrue("Exchange not created as expected",(
-                (AMQSession_0_10)jmsSession).isExchangeExist(dest, (ExchangeNode)dest.getTargetNode() , true));
+                (AMQSession_0_10)jmsSession).isExchangeExist(dest,true));
        
         // The existence of the queue is implicitly tested here
         assertTrue("Queue not bound as expected",(
@@ -367,7 +365,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
     public void checkQueueForBindings(Session jmsSession, AMQDestination dest,String headersBinding) throws Exception
     {
     	assertTrue("Queue not created as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));              
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, true));
         
         assertTrue("Queue not bound as expected",(
                 (AMQSession_0_10)jmsSession).isQueueBound("", 
@@ -506,14 +504,14 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         MessageConsumer cons3 = jmsSession.createConsumer(dest3);
         
         assertTrue("Destination1 was not created as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest1,(QueueNode)dest1.getSourceNode(), true));              
+                (AMQSession_0_10)jmsSession).isQueueExist(dest1, true));
         
         assertTrue("Destination1 was not bound as expected",(
                 (AMQSession_0_10)jmsSession).isQueueBound("", 
                     dest1.getAddressName(),dest1.getAddressName(), null));
         
         assertTrue("Destination2 was not created as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest2,(QueueNode)dest2.getSourceNode(), true));              
+                (AMQSession_0_10)jmsSession).isQueueExist(dest2,true));
         
         assertTrue("Destination2 was not bound as expected",(
                 (AMQSession_0_10)jmsSession).isQueueBound("", 
@@ -602,14 +600,14 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         cons.close();
         
         // Using the ADDR method to create a more complicated queue
-        String addr = "ADDR:amq.direct/x512; {create: receiver, " +
+        String addr = "ADDR:amq.direct/x512; {" +
         "link : {name : 'MY.RESP.QUEUE', " + 
         "x-declare : { auto-delete: true, exclusive: true, " +
                      "arguments : {'qpid.max_size': 1000, 'qpid.policy_type': ring} } } }";
         queue = ssn.createQueue(addr);
         
-        prod = ssn.createProducer(queue); 
         cons = ssn.createConsumer(queue);
+        prod = ssn.createProducer(queue);
         assertTrue("MY.RESP.QUEUE was not created as expected",(
                 (AMQSession_0_10)ssn).isQueueBound("amq.direct", 
                     "MY.RESP.QUEUE","x512", null));
@@ -677,8 +675,8 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         
         // Using the ADDR method to create a more complicated topic
         topic = ssn.createTopic(addr);
-        prod = ssn.createProducer(topic); 
         cons = ssn.createConsumer(topic);
+        prod = ssn.createProducer(topic);
         
         assertTrue("The queue was not bound to vehicle exchange using bus as the binding key",(
                 (AMQSession_0_10)ssn).isQueueBound("vehicles", 
@@ -778,7 +776,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
     public void testSubscriptionForSameDestination() throws Exception
     {
         Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);        
-        Destination dest = ssn.createTopic("ADDR:amq.topic/foo; {link:{durable:true}}");
+        Destination dest = ssn.createTopic("ADDR:amq.topic/foo");
         MessageConsumer consumer1 = ssn.createConsumer(dest);
         MessageConsumer consumer2 = ssn.createConsumer(dest);
         MessageProducer prod = ssn.createProducer(dest);
@@ -840,7 +838,8 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         		"}";
         
         // Using the ADDR method to create a more complicated topic
-        MessageConsumer  cons = ssn.createConsumer(new AMQAnyDestination(addr));
+        Topic topic = ssn.createTopic(addr);
+        MessageConsumer  cons = ssn.createConsumer(topic);
         
         assertTrue("The queue was not bound to MRKT exchange using NYSE.# as the binding key",(
                 (AMQSession_0_10)ssn).isQueueBound("MRKT", 
@@ -854,7 +853,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
                 (AMQSession_0_10)ssn).isQueueBound("MRKT", 
                     "my-topic","CNTL.#", null));
         
-        MessageProducer prod = ssn.createProducer(ssn.createTopic(addr));
+        MessageProducer prod = ssn.createProducer(topic);
         Message msg = ssn.createTextMessage("test");
         msg.setStringProperty("qpid.subject", "NASDAQ.ABCD");
         prod.send(msg);
@@ -909,32 +908,31 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
     {
         Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);        
         
+        String bindingStr = "x-bindings:[{key:'NYSE.#'},{key:'NASDAQ.#'},{key:'CNTL.#'}]}}";
+
         Properties props = new Properties();
         props.setProperty("java.naming.factory.initial", "org.apache.qpid.jndi.PropertiesFileInitialContextFactory");
-        props.setProperty("destination.address1", "ADDR:amq.topic");
-        props.setProperty("destination.address2", "ADDR:amq.direct/test");                
-        String addrStr = "ADDR:amq.topic/test; {link:{name: my-topic," +
-                  "x-bindings:[{key:'NYSE.#'},{key:'NASDAQ.#'},{key:'CNTL.#'}]}}";
-        props.setProperty("destination.address3", addrStr);
-        props.setProperty("topic.address4", "hello.world");
-        addrStr = "ADDR:my_queue; {create:always,link: {x-subscribes:{exclusive: true, arguments: {a:b,x:y}}}}";
+        props.setProperty("destination.address1", "ADDR:amq.topic/test");
+        props.setProperty("destination.address2", "ADDR:amq.topic/test; {node:{" + bindingStr);
+        props.setProperty("destination.address3", "ADDR:amq.topic/test; {link:{" + bindingStr);
+        String addrStr = "ADDR:my_queue; {create:always,link: {x-subscribes:{exclusive: true, arguments: {a:b,x:y}}}}";
         props.setProperty("destination.address5", addrStr); 
         
         Context ctx = new InitialContext(props);       
 
-        for (int i=1; i < 5; i++)
+        for (int i=1; i < 4; i++)
         {
             Topic topic = (Topic) ctx.lookup("address"+i);
-            createDurableSubscriber(ctx,ssn,"address"+i,topic);
+            createDurableSubscriber(ctx,ssn,"address"+i,topic,"ADDR:amq.topic/test");
         }
         
         Topic topic = ssn.createTopic("ADDR:news.us");
-        createDurableSubscriber(ctx,ssn,"my-dest",topic);
+        createDurableSubscriber(ctx,ssn,"my-dest",topic,"ADDR:news.us");
         
         Topic namedQueue = (Topic) ctx.lookup("address5");
         try
         {
-            createDurableSubscriber(ctx,ssn,"my-queue",namedQueue);
+            createDurableSubscriber(ctx,ssn,"my-queue",namedQueue,"ADDR:amq.topic/test");
             fail("Exception should be thrown. Durable subscribers cannot be created for Queues");
         }
         catch(JMSException e)
@@ -943,16 +941,74 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
                     e.getMessage());
         }
     }
-    
-    private void createDurableSubscriber(Context ctx,Session ssn,String destName,Topic topic) throws Exception
+
+    public void testDurableSubscription() throws Exception
+    {
+        Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+        Topic topic = session.createTopic("ADDR:amq.topic/" + getTestQueueName());
+        MessageProducer publisher = session.createProducer(topic);
+        MessageConsumer subscriber = session.createDurableSubscriber(topic, getTestQueueName());
+
+        TextMessage messageToSend = session.createTextMessage("Test0");
+        publisher.send(messageToSend);
+        ((AMQSession)session).sync();
+
+        Message receivedMessage = subscriber.receive(1000);
+        assertNotNull("Message has not been received", receivedMessage);
+        assertEquals("Unexpected message", messageToSend.getText(), ((TextMessage)receivedMessage).getText());
+
+        subscriber.close();
+
+        messageToSend = session.createTextMessage("Test1");
+        publisher.send(messageToSend);
+        ((AMQSession)session).sync();
+
+        subscriber = session.createDurableSubscriber(topic, getTestQueueName());
+        receivedMessage = subscriber.receive(1000);
+        assertNotNull("Message has not been received", receivedMessage);
+        assertEquals("Unexpected message", messageToSend.getText(), ((TextMessage)receivedMessage).getText());
+    }
+
+    public void testDurableSubscriptionnWithSelector() throws Exception
+    {
+        Session session = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+        Topic topic = session.createTopic("ADDR:amq.topic/" + getTestQueueName());
+        MessageProducer publisher = session.createProducer(topic);
+        MessageConsumer subscriber = session.createDurableSubscriber(topic, getTestQueueName(), "id=1", false);
+
+        TextMessage messageToSend = session.createTextMessage("Test0");
+        messageToSend.setIntProperty("id", 1);
+        publisher.send(messageToSend);
+        ((AMQSession)session).sync();
+
+        Message receivedMessage = subscriber.receive(1000);
+        assertNotNull("Message has not been received", receivedMessage);
+        assertEquals("Unexpected message", messageToSend.getText(), ((TextMessage)receivedMessage).getText());
+        assertEquals("Unexpected id", 1, receivedMessage.getIntProperty("id"));
+
+        subscriber.close();
+
+        messageToSend = session.createTextMessage("Test1");
+        messageToSend.setIntProperty("id", 1);
+        publisher.send(messageToSend);
+        ((AMQSession)session).sync();
+
+        subscriber = session.createDurableSubscriber(topic, getTestQueueName(), "id=1", false);
+        receivedMessage = subscriber.receive(1000);
+        assertNotNull("Message has not been received", receivedMessage);
+        assertEquals("Unexpected message", messageToSend.getText(), ((TextMessage)receivedMessage).getText());
+        assertEquals("Unexpected id", 1, receivedMessage.getIntProperty("id"));
+    }
+
+    private void createDurableSubscriber(Context ctx,Session ssn,String destName,Topic topic, String producerAddr) throws Exception
     {        
         MessageConsumer cons = ssn.createDurableSubscriber(topic, destName);
-        MessageProducer prod = ssn.createProducer(topic);
+        MessageProducer prod = ssn.createProducer(ssn.createTopic(producerAddr));
         
         Message m = ssn.createTextMessage(destName);
         prod.send(m);
         Message msg = cons.receive(1000);
-        assertNotNull(msg);
+        assertNotNull("Message not received as expected when using Topic : " + topic,msg);
         assertEquals(destName,((TextMessage)msg).getText());
         ssn.unsubscribe(destName);
     }
@@ -977,7 +1033,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         }
         
         assertFalse("Queue not deleted as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));  
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, false));
         
         
         String addr2 = "ADDR:testQueue2;{create: always, delete: receiver}";
@@ -993,7 +1049,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         }
         
         assertFalse("Queue not deleted as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));  
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, false));
 
         
         String addr3 = "ADDR:testQueue3;{create: always, delete: sender}";
@@ -1010,9 +1066,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         }
         
         assertFalse("Queue not deleted as expected",(
-                (AMQSession_0_10)jmsSession).isQueueExist(dest,(QueueNode)dest.getSourceNode(), true));  
-
-        
+                (AMQSession_0_10)jmsSession).isQueueExist(dest, false));
     }
     
     /**
@@ -1094,7 +1148,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         MessageConsumer cons = ssn.createConsumer(ssn.createTopic("ADDR:amq.topic/test"));
         MessageProducer prod = ssn.createProducer(null);
         
-        Queue queue = ssn.createQueue("ADDR:amq.topic/test");
+        Topic queue = ssn.createTopic("ADDR:amq.topic/test");
         prod.send(queue,ssn.createTextMessage("A"));
         
         Message msg = cons.receive(1000);
@@ -1307,4 +1361,62 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase
         assertNotNull("message should be re-received by consumer after rollback", receivedMessage);
         jmsSession.commit();
     }
+
+    /**
+     * Test Goals :
+     *
+     * 1. Verify that link bindings are created and destroyed after creating and closing a subscriber.
+     * 2. Verify that link bindings are created and destroyed after creating and closing a subscriber.
+     */
+    public void testLinkBindingBehavior() throws Exception
+    {
+        Session jmsSession = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
+        String addr = "ADDR:my-queue; {create: always, " +
+              "link: " +
+              "{" +
+                   "x-bindings: [{exchange : 'amq.direct', key : test}]," +
+              "}" +
+        "}";
+
+        AMQDestination dest = (AMQDestination)jmsSession.createQueue(addr);
+        MessageConsumer cons = jmsSession.createConsumer(dest);
+        AMQSession_0_10 ssn = (AMQSession_0_10)jmsSession;
+
+        assertTrue("Queue not created as expected",ssn.isQueueExist(dest, true));
+        assertTrue("Queue not bound as expected",ssn.isQueueBound("amq.direct","my-queue","test", null));
+
+        cons.close(); // closing consumer, link binding should be removed now.
+        assertTrue("Queue should still be there",ssn.isQueueExist(dest, true));
+        assertFalse("Binding should not exist anymore",ssn.isQueueBound("amq.direct","my-queue","test", null));
+
+        MessageProducer prod = jmsSession.createProducer(dest);
+        assertTrue("Queue not bound as expected",ssn.isQueueBound("amq.direct","my-queue","test", null));
+        prod.close();
+        assertFalse("Binding should not exist anymore",ssn.isQueueBound("amq.direct","my-queue","test", null));
+    }
+
+    /**
+     * Test Goals : Verifies that the subscription queue created is as specified under link properties.
+     */
+    public void testCustomizingSubscriptionQueue() throws Exception
+    {
+        Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE);
+        String xDeclareArgs = "x-declare: { exclusive: false, auto-delete: false," +
+                                           "alternate-exchange: 'amq.fanout'," +
+                                           "arguments: {'qpid.max_size': 1000,'qpid.max_count': 100}" +
+                                          "}";
+
+        String addr = "ADDR:amq.topic/test; {link: {name:my-queue, durable:true," + xDeclareArgs + "}}";
+        Destination dest = ssn.createTopic(addr);
+        MessageConsumer cons = ssn.createConsumer(dest);
+
+        String verifyAddr = "ADDR:my-queue;{ node: {durable:true, " + xDeclareArgs + "}}";
+        AMQDestination verifyDest = (AMQDestination)ssn.createQueue(verifyAddr);
+        ((AMQSession_0_10)ssn).isQueueExist(verifyDest, true);
+
+        // Verify that the producer does not delete the subscription queue.
+        MessageProducer prod = ssn.createProducer(dest);
+        prod.close();
+        ((AMQSession_0_10)ssn).isQueueExist(verifyDest, true);
+    }
 }
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java
index b82c3756f2..2875e2c6b1 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/failover/FailoverTest.java
@@ -24,6 +24,7 @@ package org.apache.qpid.test.client.failover;
 import org.apache.log4j.Logger;
 
 import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
 import org.apache.qpid.jms.ConnectionListener;
 import org.apache.qpid.test.utils.FailoverBaseCase;
 
@@ -35,7 +36,6 @@ import javax.jms.MessageProducer;
 import javax.jms.Queue;
 import javax.jms.Session;
 import javax.jms.TextMessage;
-import javax.naming.NamingException;
 import java.util.Random;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -75,7 +75,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener
         failoverComplete = new CountDownLatch(1);
     }
 
-    protected void init(boolean transacted, int mode) throws JMSException, NamingException
+    private void init(boolean transacted, int mode) throws Exception
     {
         consumerSession = connection.createSession(transacted, mode);
         queue = consumerSession.createQueue(getName()+System.currentTimeMillis());
@@ -125,7 +125,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener
         }
     }
 
-    private void sendMessages(int startIndex,int endIndex, boolean transacted) throws JMSException
+    private void sendMessages(int startIndex,int endIndex, boolean transacted) throws Exception
     {
         _logger.debug("**************** Send (Start: " + startIndex + ", End:" + endIndex + ")***********************");
         
@@ -144,6 +144,10 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener
         {
             producerSession.commit();
         }
+        else
+        {
+            ((AMQSession)producerSession).sync();
+        }
     }
 
     public void testP2PFailover() throws Exception
@@ -163,13 +167,13 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener
     {
         if (CLUSTERED)
         {    
-            testP2PFailover(numMessages, false,true, false);
+            testP2PFailover(numMessages, false, true, false);
         }
     }    
      
     public void testP2PFailoverTransacted() throws Exception
     {
-        testP2PFailover(numMessages, true,true, false);
+        testP2PFailover(numMessages, true,true, true);
     }
 
     public void testP2PFailoverTransactedWithMessagesLeftToConsumeAndProduce() throws Exception
@@ -177,17 +181,16 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener
         // Currently the cluster does not support transactions that span a failover
         if (CLUSTERED)
         {
-            testP2PFailover(numMessages, false,false, false);
+            testP2PFailover(numMessages, false, false, false);
         }
     }
-
-    private void testP2PFailover(int totalMessages, boolean consumeAll, boolean produceAll , boolean transacted) throws JMSException, NamingException
+    private void testP2PFailover(int totalMessages, boolean consumeAll, boolean produceAll , boolean transacted) throws Exception
     {        
         init(transacted, Session.AUTO_ACKNOWLEDGE);
         runP2PFailover(totalMessages,consumeAll, produceAll , transacted);
     } 
-    
-    protected void runP2PFailover(int totalMessages, boolean consumeAll, boolean produceAll , boolean transacted) throws JMSException, NamingException
+
+    private void runP2PFailover(int totalMessages, boolean consumeAll, boolean produceAll , boolean transacted) throws Exception
     {
         int toProduce = totalMessages;
         
@@ -254,7 +257,7 @@ public class FailoverTest extends FailoverBaseCase implements ConnectionListener
             //evil ignore IE.
         }
     }
-   
+
     public void testClientAckFailover() throws Exception
     {
         init(false, Session.CLIENT_ACKNOWLEDGE);
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java
index 5b350d2d89..3cc15d5e9d 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java
@@ -63,8 +63,7 @@ public class JMSDestinationTest extends QpidBrokerTestCase
 
     public void setUp() throws Exception
     {
-        //Ensure JMX management is enabled for MovedToQueue test 
-        setConfigurationProperty("management.enabled", "true");
+        getBrokerConfiguration().addJmxManagementConfiguration();
 
         super.setUp();
 
diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java
index ee81e7c372..9bf7dbd62a 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java
@@ -54,11 +54,9 @@ public class SyncWaitDelayTest extends QpidBrokerTestCase
     public void setUp() throws Exception
     {
 
-        setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.class", "org.apache.qpid.server.store.SlowMessageStore");
-        setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.delays.commitTran.post", String.valueOf(POST_COMMIT_DELAY));
-        setConfigurationProperty("management.enabled", "false");
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.class", "org.apache.qpid.server.store.SlowMessageStore");
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST+".store.delays.commitTran.post", String.valueOf(POST_COMMIT_DELAY));
 
-        
         super.setUp();
 
         //Set the syncWrite timeout to be just larger than the delay on the commitTran.
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
index 53f37cd915..8961574d1e 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/basic/InvalidDestinationTest.java
@@ -21,16 +21,23 @@
 
 package org.apache.qpid.test.unit.basic;
 
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
+import java.util.Collections;
+import java.util.Map;
+import javax.jms.Connection;
 import javax.jms.InvalidDestinationException;
+import javax.jms.JMSException;
+import javax.jms.MessageProducer;
 import javax.jms.Queue;
 import javax.jms.QueueSender;
 import javax.jms.QueueSession;
 import javax.jms.Session;
 import javax.jms.TextMessage;
+import javax.jms.Topic;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQQueue;
+import org.apache.qpid.configuration.ClientProperties;
+import org.apache.qpid.jms.ConnectionURL;
+import org.apache.qpid.test.utils.QpidBrokerTestCase;
 
 public class InvalidDestinationTest extends QpidBrokerTestCase
 {
@@ -48,21 +55,23 @@ public class InvalidDestinationTest extends QpidBrokerTestCase
         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);
 
+        Queue invalidDestination = queueSession.createQueue("unknownQ");
+
+        Queue validDestination = queueSession.createQueue(getTestQueueName());
+
         // This is the only easy way to create and bind a queue from the API :-(
         queueSession.createConsumer(validDestination);
+        QueueSender sender;
+        TextMessage msg= queueSession.createTextMessage("Hello");
 
-        QueueSender sender = queueSession.createSender(invalidDestination);
-        TextMessage msg = queueSession.createTextMessage("Hello");
         try
         {
+            sender = queueSession.createSender(invalidDestination);
+
             sender.send(msg);
             fail("Expected InvalidDestinationException");
         }
@@ -70,10 +79,8 @@ public class InvalidDestinationTest extends QpidBrokerTestCase
         {
             // pass
         }
-        sender.close();
 
         sender = queueSession.createSender(null);
-        invalidDestination = new AMQQueue("amq.direct","unknownQ");
 
         try
         {
@@ -86,19 +93,79 @@ public class InvalidDestinationTest extends QpidBrokerTestCase
         }
         sender.send(validDestination,msg);
         sender.close();
-        validDestination = new AMQQueue("amq.direct","knownQ");
         sender = queueSession.createSender(validDestination);
         sender.send(msg);
+    }
 
+    /**
+     * Tests that specifying the {@value ClientProperties#VERIFY_QUEUE_ON_SEND} system property
+     * results in an exception when sending to an invalid queue destination.
+     */
+    public void testInvalidDestinationOnMessageProducer() throws Exception
+    {
+        setTestSystemProperty(ClientProperties.VERIFY_QUEUE_ON_SEND, "true");
+        final AMQConnection connection = (AMQConnection) getConnection();
+        doInvalidDestinationOnMessageProducer(connection);
+    }
 
+    /**
+     * Tests that specifying the {@value ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND}
+     * connection URL option property results in an exception when sending to an
+     * invalid queue destination.
+     */
+    public void testInvalidDestinationOnMessageProducerURL() throws Exception
+    {
+        Map options = Collections.singletonMap(ConnectionURL.OPTIONS_VERIFY_QUEUE_ON_SEND, "true");
+        doInvalidDestinationOnMessageProducer(getConnectionWithOptions(options));
+    }
 
+    private void doInvalidDestinationOnMessageProducer(Connection connection) throws JMSException
+    {
+        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
 
-    }
+        String invalidQueueName = getTestQueueName() + "UnknownQ";
+        Queue invalidDestination = session.createQueue(invalidQueueName);
 
+        String validQueueName = getTestQueueName() + "KnownQ";
+        Queue validDestination = session.createQueue(validQueueName);
 
-    public static junit.framework.Test suite()
-    {
+        // This is the only easy way to create and bind a queue from the API :-(
+        session.createConsumer(validDestination);
+
+        MessageProducer sender;
+        TextMessage msg = session.createTextMessage("Hello");
+        try
+        {
+            sender = session.createProducer(invalidDestination);
+            sender.send(msg);
+            fail("Expected InvalidDestinationException");
+        }
+        catch (InvalidDestinationException ex)
+        {
+            // pass
+        }
 
-        return new junit.framework.TestSuite(InvalidDestinationTest.class);
+        sender = session.createProducer(null);
+        invalidDestination = new AMQQueue("amq.direct",invalidQueueName);
+
+        try
+        {
+            sender.send(invalidDestination,msg);
+            fail("Expected InvalidDestinationException");
+        }
+        catch (InvalidDestinationException ex)
+        {
+            // pass
+        }
+        sender.send(validDestination, msg);
+        sender.close();
+        sender = session.createProducer(validDestination);
+        sender.send(msg);
+
+        //Verify sending to an 'invalid' Topic doesn't throw an exception
+        String invalidTopic = getTestQueueName() + "UnknownT";
+        Topic topic = session.createTopic(invalidTopic);
+        sender = session.createProducer(topic);
+        sender.send(msg);
     }
 }
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java
index 8577fb5b6a..4e9477f4b6 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java
@@ -20,26 +20,59 @@
  */
 package org.apache.qpid.test.unit.client;
 
+import java.io.IOException;
+
 import org.apache.qpid.AMQException;
+import org.apache.qpid.configuration.ClientProperties;
+import org.apache.qpid.management.common.mbeans.ManagedExchange;
 import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.test.utils.JMXTestUtils;
 import org.apache.qpid.test.utils.QpidBrokerTestCase;
+import org.apache.qpid.url.BindingURL;
 
 import javax.jms.Connection;
 import javax.jms.JMSException;
 import javax.jms.Queue;
 import javax.jms.Session;
 
-/**
- * QPID-155
- *
- * Test to validate that setting the respective qpid.declare_queues,
- * qpid.declare_exchanges system properties functions as expected.
- */
 public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase
 {
-    public void testQueueDeclare() throws Exception
+    private JMXTestUtils _jmxUtils;
+
+    @Override
+    public void setUp() throws Exception
+    {
+        _jmxUtils = new JMXTestUtils(this);
+        _jmxUtils.setUp();
+
+        super.setUp();
+        _jmxUtils.open();
+    }
+
+    @Override
+    public void tearDown() throws Exception
     {
-        setSystemProperty("qpid.declare_queues", "false");
+        try
+        {
+            if (_jmxUtils != null)
+            {
+                _jmxUtils.close();
+            }
+        }
+        finally
+        {
+            super.tearDown();
+        }
+    }
+
+    /*
+     * Tests to validate that setting the respective qpid.declare_queues,
+     * qpid.declare_exchanges system properties functions as expected.
+     */
+
+    public void testQueueNotDeclaredDuringConsumerCreation() throws Exception
+    {
+        setSystemProperty(ClientProperties.QPID_DECLARE_QUEUES_PROP_NAME, "false");
 
         Connection connection = getConnection();
 
@@ -58,16 +91,16 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase
         }
     }
 
-    public void testExchangeDeclare() throws Exception
+    public void testExchangeNotDeclaredDuringConsumerCreation() throws Exception
     {
-        setSystemProperty("qpid.declare_exchanges", "false");
+        setSystemProperty(ClientProperties.QPID_DECLARE_EXCHANGES_PROP_NAME, "false");
 
         Connection connection = getConnection();
 
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
 
-        String EXCHANGE_TYPE = "test.direct";
-        Queue queue = session.createQueue("direct://" + EXCHANGE_TYPE + "/queue/queue");
+        String exchangeName = getTestQueueName();
+        Queue queue = session.createQueue("direct://" + exchangeName + "/queue/queue");
 
         try
         {
@@ -78,6 +111,50 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase
         {
             checkExceptionErrorCode(e, AMQConstant.NOT_FOUND);
         }
+
+        //verify the exchange was not declared
+        String exchangeObjectName = _jmxUtils.getExchangeObjectName("test", exchangeName);
+        assertFalse("exchange should not exist", _jmxUtils.doesManagedObjectExist(exchangeObjectName));
+    }
+
+    /**
+     * Checks that setting {@value ClientProperties#QPID_DECLARE_EXCHANGES_PROP_NAME} false results in
+     * disabling implicit ExchangeDeclares during producer creation when using a {@link BindingURL}
+     */
+    public void testExchangeNotDeclaredDuringProducerCreation() throws Exception
+    {
+        Connection connection = getConnection();
+        Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+        String exchangeName1 = getTestQueueName() + "1";
+
+
+        Queue queue = session1.createQueue("direct://" + exchangeName1 + "/queue/queue");
+        session1.createProducer(queue);
+
+        //close the session to ensure any previous commands were fully processed by
+        //the broker before observing their effect
+        session1.close();
+
+        //verify the exchange was declared
+        String exchangeObjectName = _jmxUtils.getExchangeObjectName("test", exchangeName1);
+        assertTrue("exchange should exist", _jmxUtils.doesManagedObjectExist(exchangeObjectName));
+
+        //Now disable the implicit exchange declares and try again
+        setSystemProperty(ClientProperties.QPID_DECLARE_EXCHANGES_PROP_NAME, "false");
+
+        Session session2 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+        String exchangeName2 = getTestQueueName() + "2";
+
+        Queue queue2 = session2.createQueue("direct://" + exchangeName2 + "/queue/queue");
+        session2.createProducer(queue2);
+
+        //close the session to ensure any previous commands were fully processed by
+        //the broker before observing their effect
+        session2.close();
+
+        //verify the exchange was not declared
+        String exchangeObjectName2 = _jmxUtils.getExchangeObjectName("test", exchangeName2);
+        assertFalse("exchange should not exist", _jmxUtils.doesManagedObjectExist(exchangeObjectName2));
     }
 
     private void checkExceptionErrorCode(JMSException original, AMQConstant code)
@@ -87,4 +164,71 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase
         assertTrue("Linked exception should be an AMQException", linked instanceof AMQException);
         assertEquals("Error code should be " + code.getCode(), code, ((AMQException) linked).getErrorCode());
     }
+
+    /*
+     * Tests to validate that the custom exchanges declared by the client during
+     * consumer and producer creation have the expected properties.
+     */
+
+    public void testPropertiesOfCustomExchangeDeclaredDuringProducerCreation() throws Exception
+    {
+        implTestPropertiesOfCustomExchange(true, false);
+    }
+
+    public void testPropertiesOfCustomExchangeDeclaredDuringConsumerCreation() throws Exception
+    {
+        implTestPropertiesOfCustomExchange(false, true);
+    }
+
+    private void implTestPropertiesOfCustomExchange(boolean createProducer, boolean createConsumer) throws Exception
+    {
+        Connection connection = getConnection();
+
+        Session session1 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+        String exchangeName1 = getTestQueueName() + "1";
+        String queueName1 = getTestQueueName() + "1";
+
+        Queue queue = session1.createQueue("direct://" + exchangeName1 + "/" + queueName1 + "/" + queueName1 + "?" + BindingURL.OPTION_EXCHANGE_AUTODELETE + "='true'");
+        if(createProducer)
+        {
+            session1.createProducer(queue);
+        }
+
+        if(createConsumer)
+        {
+            session1.createConsumer(queue);
+        }
+        session1.close();
+
+        //verify the exchange was declared to expectation
+        verifyDeclaredExchange(exchangeName1, true, false);
+
+        Session session2 = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+        String exchangeName2 = getTestQueueName() + "2";
+        String queueName2 = getTestQueueName() + "2";
+
+        Queue queue2 = session2.createQueue("direct://" + exchangeName2 + "/" + queueName2 + "/" + queueName2 + "?" + BindingURL.OPTION_EXCHANGE_DURABLE + "='true'");
+        if(createProducer)
+        {
+            session2.createProducer(queue2);
+        }
+
+        if(createConsumer)
+        {
+            session2.createConsumer(queue2);
+        }
+        session2.close();
+
+        //verify the exchange was declared to expectation
+        verifyDeclaredExchange(exchangeName2, false, true);
+    }
+
+    private void verifyDeclaredExchange(String exchangeName, boolean isAutoDelete, boolean isDurable) throws IOException
+    {
+        String exchangeObjectName = _jmxUtils.getExchangeObjectName("test", exchangeName);
+        assertTrue("exchange should exist", _jmxUtils.doesManagedObjectExist(exchangeObjectName));
+        ManagedExchange exchange = _jmxUtils.getManagedExchange(exchangeName);
+        assertEquals(isAutoDelete, exchange.isAutoDelete());
+        assertEquals(isDurable,exchange.isDurable());
+    }
 }
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java
index bc1eead8b4..40db17f799 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/unit/client/MaxDeliveryCountTest.java
@@ -74,19 +74,20 @@ public class MaxDeliveryCountTest extends QpidBrokerTestCase
     public void setUp() throws Exception
     {
         //enable DLQ/maximumDeliveryCount support for all queues at the vhost level
-        setConfigurationProperty("virtualhosts.virtualhost.test.queues.maximumDeliveryCount",
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.queues.maximumDeliveryCount",
                 String.valueOf(MAX_DELIVERY_COUNT));
-        setConfigurationProperty("virtualhosts.virtualhost.test.queues.deadLetterQueues",
+        setVirtualHostConfigurationProperty("virtualhosts.virtualhost.test.queues.deadLetterQueues",
                                 String.valueOf(true));
 
         //Ensure management is on
-        setConfigurationProperty("management.enabled", "true");
-        setConfigurationProperty("management.ssl.enabled", "false");
+        getBrokerConfiguration().addJmxManagementConfiguration();
 
         // Set client-side flag to allow the server to determine if messages
         // dead-lettered or requeued.
-        setTestClientSystemProperty(ClientProperties.REJECT_BEHAVIOUR_PROP_NAME, "server");
-
+        if (!isBroker010())
+        {
+            setTestClientSystemProperty(ClientProperties.REJECT_BEHAVIOUR_PROP_NAME, "server");
+        }
         super.setUp();
 
         boolean durableSub = isDurSubTest();
diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java
deleted file mode 100644
index 1c9ee27b94..0000000000
--- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.test.unit.client.channelclose;
-
-import junit.textui.TestRunner;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQQueue;
-import org.apache.qpid.test.utils.QpidBrokerTestCase;
-
-import javax.jms.Destination;
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageListener;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Due to bizarre exception handling all sessions are closed if you get
- * a channel close request and no exception listener is registered.
- * 

- * JIRA issue IBTBLZ-10. - *

- * Simulate by: - *

- * 0. Create two sessions with no exception listener. - * 1. Publish message to queue/topic that does not exist (wrong routing key). - * 2. This will cause a channel close. - * 3. Since client does not have an exception listener, currently all sessions are - * closed. - */ -public class ChannelCloseOkTest extends QpidBrokerTestCase -{ - private AMQConnection _connection; - private Destination _destination1; - private Destination _destination2; - private Session _session1; - private Session _session2; - private final List _received1 = new ArrayList(); - private final List _received2 = new ArrayList(); - - private static final Logger _log = LoggerFactory.getLogger(ChannelCloseOkTest.class); - - protected void setUp() throws Exception - { - super.setUp(); - - _connection = (AMQConnection) getConnection("guest", "guest"); - - _destination1 = new AMQQueue(_connection, "q1", true); - _destination2 = new AMQQueue(_connection, "q2", true); - _session1 = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - _session1.createConsumer(_destination1).setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - _log.debug("consumer 1 got message [" + getTextMessage(message) + "]"); - synchronized (_received1) - { - _received1.add(message); - _received1.notify(); - } - } - }); - _session2 = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - _session2.createConsumer(_destination2).setMessageListener(new MessageListener() - { - public void onMessage(Message message) - { - _log.debug("consumer 2 got message [" + getTextMessage(message) + "]"); - synchronized (_received2) - { - _received2.add(message); - _received2.notify(); - } - } - }); - - _connection.start(); - } - - private String getTextMessage(Message message) - { - TextMessage tm = (TextMessage) message; - try - { - return tm.getText(); - } - catch (JMSException e) - { - return "oops " + e; - } - } - - protected void tearDown() throws Exception - { - closeConnection(); - super.tearDown(); - } - - public void closeConnection() throws JMSException - { - if (_connection != null) - { - _log.info(">>>>>>>>>>>>>>.. closing"); - _connection.close(); - } - } - - public void testWithoutExceptionListener() throws Exception - { - doTest(); - } - - public void testWithExceptionListener() throws Exception - { - _connection.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException jmsException) - { - _log.warn("onException - " + jmsException.getMessage()); - } - }); - - doTest(); - } - - public void doTest() throws Exception - { - // Check both sessions are ok. - sendAndWait(_session1, _destination1, "first", _received1, 1); - sendAndWait(_session2, _destination2, "second", _received2, 1); - assertEquals(1, _received1.size()); - assertEquals(1, _received2.size()); - - // Now send message to incorrect destination on session 1. - Destination destination = new AMQQueue(_connection, "incorrect"); - send(_session1, destination, "third"); // no point waiting as message will never be received. - - // Ensure both sessions are still ok. - // Send a bunch of messages as this give time for the sessions to be erroneously closed. - final int num = 300; - for (int i = 0; i < num; ++i) - { - send(_session1, _destination1, "" + i); - send(_session2, _destination2, "" + i); - } - - waitFor(_received1, num + 1); - waitFor(_received2, num + 1); - - // Note that the third message is never received as it is sent to an incorrect destination. - assertEquals(num + 1, _received1.size()); - assertEquals(num + 1, _received2.size()); - } - - private void sendAndWait(Session session, Destination destination, String message, List received, int count) - throws JMSException, InterruptedException - { - send(session, destination, message); - waitFor(received, count); - } - - private void send(Session session, Destination destination, String message) throws JMSException - { - _log.debug("sending message " + message); - MessageProducer producer1 = session.createProducer(destination); - producer1.send(session.createTextMessage(message)); - } - - private void waitFor(List received, int count) throws InterruptedException - { - long timeout = 20000; - - synchronized (received) - { - long start = System.currentTimeMillis(); - while (received.size() < count) - { - if (System.currentTimeMillis() - start > timeout) - { - fail("timeout expired waiting for messages"); - } - try - { - received.wait(timeout); - } - catch (InterruptedException e) - { - _log.info("Interrupted: " + e); - throw e; - } - - } - } - } - - private static String randomize(String in) - { - return in + System.currentTimeMillis(); - } - - public static void main(String[] args) - { - TestRunner.run(ChannelCloseOkTest.class); - } - - public static junit.framework.Test suite() - { - return new junit.framework.TestSuite(ChannelCloseOkTest.class); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java deleted file mode 100644 index c20eefd987..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ -package org.apache.qpid.test.unit.client.channelclose; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.failover.FailoverException; -import org.apache.qpid.client.protocol.AMQProtocolHandler; -import org.apache.qpid.framing.AMQFrame; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ChannelCloseOkBody; -import org.apache.qpid.framing.ChannelOpenBody; -import org.apache.qpid.framing.ChannelOpenOkBody; -import org.apache.qpid.framing.ExchangeDeclareBody; -import org.apache.qpid.framing.ExchangeDeclareOkBody; -import org.apache.qpid.jms.ConnectionListener; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.test.utils.QpidBrokerTestCase; - -import javax.jms.Connection; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TextMessage; - -public class ChannelCloseTest extends QpidBrokerTestCase implements ExceptionListener, ConnectionListener -{ - private static final Logger _logger = LoggerFactory.getLogger(ChannelCloseTest.class); - - private Connection _connection; - private Session _session; - private static final long SYNC_TIMEOUT = 500; - private int TEST = 0; - - /** - * Close channel, use chanel with same id ensure error. - * - * This test is only valid for non 0-10 connection . - */ - public void testReusingChannelAfterFullClosure() throws Exception - { - _connection=newConnection(); - - // Create Producer - try - { - _connection.start(); - - createChannelAndTest(1); - - // Cause it to close - try - { - _logger.info("Testing invalid exchange"); - declareExchange(1, "", "name_that_will_lookup_to_null", false); - fail("Exchange name is empty so this should fail "); - } - catch (AMQException e) - { - assertEquals("Exchange should not be found", AMQConstant.NOT_FOUND, e.getErrorCode()); - } - - // Check that - try - { - _logger.info("Testing valid exchange should fail"); - declareExchange(1, "topic", "amq.topic", false); - fail("This should not succeed as the channel should be closed "); - } - catch (AMQException e) - { - if (_logger.isInfoEnabled()) - { - _logger.info("Exception occured was:" + e.getErrorCode()); - } - - assertEquals("Connection should be closed", AMQConstant.CHANNEL_ERROR, e.getErrorCode()); - - _connection=newConnection(); - } - - checkSendingMessage(); - - _session.close(); - _connection.close(); - - } - catch (JMSException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - } - - /* - close channel and send guff then send ok no errors - REMOVE TEST - The behaviour after server has sent close is undefined. - the server should be free to fail as it may wish to reclaim its resources - immediately after close. - */ - /*public void testSendingMethodsAfterClose() throws Exception - { - // this is testing an 0.8 connection - if(isBroker08()) - { - try - { - _connection=new AMQConnection("amqp://guest:guest@CCTTest/test?brokerlist='" + _brokerlist + "'"); - - ((AMQConnection) _connection).setConnectionListener(this); - - _connection.setExceptionListener(this); - - // Change the StateManager for one that doesn't respond with Close-OKs - AMQStateManager oldStateManager=((AMQConnection) _connection).getProtocolHandler().getStateManager(); - - _session=_connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); - - _connection.start(); - - // Test connection - checkSendingMessage(); - - // Set StateManager to manager that ignores Close-oks - AMQProtocolSession protocolSession= - ((AMQConnection) _connection).getProtocolHandler().getProtocolSession(); - - MethodDispatcher d = protocolSession.getMethodDispatcher(); - - MethodDispatcher wrappedDispatcher = (MethodDispatcher) - Proxy.newProxyInstance(d.getClass().getClassLoader(), - d.getClass().getInterfaces(), - new MethodDispatcherProxyHandler( - (ClientMethodDispatcherImpl) d)); - - protocolSession.setMethodDispatcher(wrappedDispatcher); - - - AMQStateManager newStateManager=new NoCloseOKStateManager(protocolSession); - newStateManager.changeState(oldStateManager.getCurrentState()); - - ((AMQConnection) _connection).getProtocolHandler().setStateManager(newStateManager); - - final int TEST_CHANNEL=1; - _logger.info("Testing Channel(" + TEST_CHANNEL + ") Creation"); - - createChannelAndTest(TEST_CHANNEL); - - // Cause it to close - try - { - _logger.info("Closing Channel - invalid exchange"); - declareExchange(TEST_CHANNEL, "", "name_that_will_lookup_to_null", false); - fail("Exchange name is empty so this should fail "); - } - catch (AMQException e) - { - assertEquals("Exchange should not be found", AMQConstant.NOT_FOUND, e.getErrorCode()); - } - - try - { - // Send other methods that should be ignored - // send them no wait as server will ignore them - _logger.info("Tested known exchange - should ignore"); - declareExchange(TEST_CHANNEL, "topic", "amq.topic", true); - - _logger.info("Tested known invalid exchange - should ignore"); - declareExchange(TEST_CHANNEL, "", "name_that_will_lookup_to_null", true); - - _logger.info("Tested known invalid exchange - should ignore"); - declareExchange(TEST_CHANNEL, "", "name_that_will_lookup_to_null", true); - - // Send sync .. server will igore and timy oue - _logger.info("Tested known invalid exchange - should ignore"); - declareExchange(TEST_CHANNEL, "", "name_that_will_lookup_to_null", false); - } - catch (AMQTimeoutException te) - { - assertEquals("Request should timeout", AMQConstant.REQUEST_TIMEOUT, te.getErrorCode()); - } - catch (AMQException e) - { - fail("This should not fail as all requests should be ignored"); - } - - _logger.info("Sending Close"); - // Send Close-ok - sendClose(TEST_CHANNEL); - - _logger.info("Re-opening channel"); - - createChannelAndTest(TEST_CHANNEL); - - // Test connection is still ok - - checkSendingMessage(); - - } - catch (JMSException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - catch (AMQException e) - { - fail(e.getMessage()); - - } - catch (URLSyntaxException e) - { - fail(e.getMessage()); - } - finally - { - try - { - _session.close(); - _connection.close(); - } - catch (JMSException e) - { - e.printStackTrace(); - fail(e.getMessage()); - } - } - } - } -*/ - private void createChannelAndTest(int channel) throws FailoverException - { - // Create A channel - try - { - createChannel(channel); - } - catch (AMQException e) - { - fail(e.getMessage()); - } - - // Test it is ok - try - { - declareExchange(channel, "topic", "amq.topic", false); - _logger.info("Tested known exchange"); - } - catch (AMQException e) - { - fail("This should not fail as this is the default exchange details"); - } - } - - private void sendClose(int channel) - { - ChannelCloseOkBody body = - ((AMQConnection) _connection).getProtocolHandler().getMethodRegistry().createChannelCloseOkBody(); - AMQFrame frame = body.generateFrame(channel); - - ((AMQConnection) _connection).getProtocolHandler().writeFrame(frame); - } - - private void checkSendingMessage() throws JMSException - { - TEST++; - _logger.info("Test creating producer which will use channel id 1"); - - Queue queue = _session.createQueue("CCT_test_validation_queue" + TEST); - - MessageConsumer consumer = _session.createConsumer(queue); - - MessageProducer producer = _session.createProducer(queue); - - final String MESSAGE = "CCT_Test_Message"; - producer.send(_session.createTextMessage(MESSAGE)); - - Message msg = consumer.receive(2000); - - assertNotNull("Received messages should not be null.", msg); - assertEquals("Message received not what we sent", MESSAGE, ((TextMessage) msg).getText()); - } - - private Connection newConnection() - { - Connection connection = null; - try - { - connection = getConnection(); - - ((AMQConnection) connection).setConnectionListener(this); - - _session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); - - connection.start(); - - } - catch (Exception e) - { - fail("Creating new connection when:" + e.getMessage()); - } - - return connection; - } - - private void declareExchange(int channelId, String _type, String _name, boolean nowait) - throws AMQException, FailoverException - { - ExchangeDeclareBody body = - ((AMQConnection) _connection).getProtocolHandler() - .getMethodRegistry() - .createExchangeDeclareBody(0, - new AMQShortString(_name), - new AMQShortString(_type), - true, - false, - false, - false, - nowait, - null); - AMQFrame exchangeDeclare = body.generateFrame(channelId); - AMQProtocolHandler protocolHandler = ((AMQConnection) _connection).getProtocolHandler(); - - - if (nowait) - { - protocolHandler.writeFrame(exchangeDeclare); - } - else - { - protocolHandler.syncWrite(exchangeDeclare, ExchangeDeclareOkBody.class, SYNC_TIMEOUT); - } - -// return null; -// } -// }, (AMQConnection)_connection).execute(); - - } - - private void createChannel(int channelId) throws AMQException, FailoverException - { - ChannelOpenBody body = - ((AMQConnection) _connection).getProtocolHandler().getMethodRegistry().createChannelOpenBody(null); - - ((AMQConnection) _connection).getProtocolHandler().syncWrite(body.generateFrame(channelId), // outOfBand - ChannelOpenOkBody.class); - - } - - public void onException(JMSException jmsException) - { - // _logger.info("CCT" + jmsException); - fail(jmsException.getMessage()); - } - - public void bytesSent(long count) - { } - - public void bytesReceived(long count) - { } - - public boolean preFailover(boolean redirect) - { - return false; - } - - public boolean preResubscribe() - { - return false; - } - - public void failoverComplete() - { } - -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java index f2387fa99b..b43fe35a09 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/close/JavaServerCloseRaceConditionTest.java @@ -21,7 +21,7 @@ package org.apache.qpid.test.unit.close; import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.AMQSession_0_8; import org.apache.qpid.framing.AMQFrame; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ExchangeDeclareBody; @@ -81,7 +81,7 @@ public class JavaServerCloseRaceConditionTest extends QpidBrokerTestCase AMQConnection connection = (AMQConnection) getConnection(); - AMQSession session = (AMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + AMQSession_0_8 session = (AMQSession_0_8) connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // Set no wait true so that we block the connection // Also set a different exchange class string so the attempt to declare diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java index a07e531b98..a9ac028af6 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java @@ -73,7 +73,7 @@ public class DurableSubscriptionTest extends QpidBrokerTestCase public void setUp() throws Exception { - setConfigurationProperty("management.enabled", "true"); + getBrokerConfiguration().addJmxManagementConfiguration(); _jmxConnected=false; super.setUp(); } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java index fd8beffbe6..d93c7a2e71 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutDisabledTest.java @@ -29,7 +29,7 @@ public class TransactionTimeoutDisabledTest extends TransactionTimeoutTestCase protected void configure() throws Exception { // Setup housekeeping every second - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); // No transaction timeout configuration. } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java index b11df5a2a0..4dc26847da 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTest.java @@ -39,29 +39,29 @@ public class TransactionTimeoutTest extends TransactionTimeoutTestCase protected void configure() throws Exception { - // Setup housekeeping every second - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); + // Setup housekeeping every 100ms + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".housekeeping.checkPeriod", "100"); if (getName().contains("ProducerIdle")) { - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "0"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "0"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1500"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "0"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "0"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1500"); } else if (getName().contains("ProducerOpen")) { - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "0"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "0"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "0"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "0"); } else { - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); - setConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openWarn", "1000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.openClose", "2000"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleWarn", "500"); + setVirtualHostConfigurationProperty("virtualhosts.virtualhost." + VIRTUALHOST + ".transactionTimeout.idleClose", "1000"); } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java index e2b0f00ee4..721dc027c6 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/unit/transacted/TransactionTimeoutTestCase.java @@ -23,17 +23,13 @@ package org.apache.qpid.test.unit.transacted; import junit.framework.TestCase; import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.jms.ConnectionURL; -import org.apache.qpid.jms.Session; +import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.util.LogMonitor; +import javax.jms.Connection; import javax.jms.DeliveryMode; import javax.jms.ExceptionListener; import javax.jms.JMSException; @@ -41,6 +37,7 @@ import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Queue; +import javax.jms.Session; import javax.jms.TextMessage; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -61,7 +58,7 @@ public abstract class TransactionTimeoutTestCase extends QpidBrokerTestCase impl public static final String OPEN = "Open"; protected LogMonitor _monitor; - protected AMQConnection _con; + protected Connection _con; protected Session _psession, _csession; protected Queue _queue; protected MessageConsumer _consumer; @@ -89,16 +86,14 @@ public abstract class TransactionTimeoutTestCase extends QpidBrokerTestCase impl super.setUp(); // Connect to broker - String broker = ("tcp://localhost:" + DEFAULT_PORT); - ConnectionURL url = new AMQConnectionURL("amqp://guest:guest@clientid/test?brokerlist='" + broker + "'&maxprefetch='1'"); - _con = (AMQConnection) getConnection(url); + setTestClientSystemProperty(ClientProperties.MAX_PREFETCH_PROP_NAME, String.valueOf(1)); + _con = getConnection(); _con.setExceptionListener(this); _con.start(); // Create queue Session qsession = _con.createSession(true, Session.SESSION_TRANSACTED); - AMQShortString queueName = new AMQShortString("test"); - _queue = new AMQQueue(qsession.getDefaultQueueExchangeName(), queueName, queueName, false, true); + _queue = qsession.createQueue(getTestQueueName()); qsession.close(); // Create producer and consumer diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelper.java b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelper.java new file mode 100644 index 0000000000..12d286f822 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelper.java @@ -0,0 +1,79 @@ +/* Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.test.utils; + +import java.io.File; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * Generates the command to start a broker by substituting the tokens + * in the provided broker command. + * + * The command is returned as a list so that it can be easily used by a + * {@link java.lang.ProcessBuilder}. + */ +public class BrokerCommandHelper +{ + private final List _brokerCommandTemplateAsList; + + public BrokerCommandHelper(String brokerCommandTemplate) + { + _brokerCommandTemplateAsList = new LinkedList(Arrays.asList(brokerCommandTemplate.split("\\s+"))); + } + + public String[] getBrokerCommand( int port, String storePath, String storeType, File logConfigFile) + { + String[] command = new String[_brokerCommandTemplateAsList.size()]; + int i=0; + for (String commandPart : _brokerCommandTemplateAsList) + { + command[i] = commandPart + .replace("@PORT", "" + port) + .replace("@STORE_PATH", storePath) + .replace("@STORE_TYPE", storeType) + .replace("@LOG_CONFIG_FILE", '"' + logConfigFile.getAbsolutePath() + '"'); + i++; + } + return command; + } + + private int getBrokerCommandLogOptionIndex(String logOption) + { + int logOptionIndex = _brokerCommandTemplateAsList.indexOf(logOption); + if(logOptionIndex == -1) + { + throw new RuntimeException("Could not find option " + logOption + " in " + _brokerCommandTemplateAsList); + } + return logOptionIndex; + } + + + public void removeBrokerCommandLog4JFile() + { + String logOption = "-l"; + int logOptionIndex = getBrokerCommandLogOptionIndex(logOption); + if (logOptionIndex + 1 >= _brokerCommandTemplateAsList.size()) + { + throw new RuntimeException("Could not find log config location"); + } + _brokerCommandTemplateAsList.remove(logOptionIndex); + _brokerCommandTemplateAsList.remove(logOptionIndex); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelperTest.java b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelperTest.java new file mode 100644 index 0000000000..f0bcea8e6e --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/BrokerCommandHelperTest.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.test.utils; + +import static org.mockito.Mockito.*; + +import java.io.File; + +public class BrokerCommandHelperTest extends QpidTestCase +{ + private BrokerCommandHelper _brokerCommandHelper = new BrokerCommandHelper("qpid -p @PORT -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE"); + + private File logConfigFile = mock(File.class); + + @Override + public void setUp() + { + when(logConfigFile.getAbsolutePath()).thenReturn("log Config File"); + } + + public void testGetBrokerCommand() + { + String[] brokerCommand = _brokerCommandHelper.getBrokerCommand(1, "configFile", "json", logConfigFile); + + String[] expected = { "qpid", "-p", "1", "-sp", "configFile", "-st", "json", "-l", "\"log Config File\"" }; + assertEquals("Unexpected broker command", 9, brokerCommand.length); + for (int i = 0; i < expected.length; i++) + { + assertEquals("Unexpected command part value at " + i,expected[i], brokerCommand[i] ); + } + } + + public void testRemoveBrokerCommandLog4JFile() + { + _brokerCommandHelper.removeBrokerCommandLog4JFile(); + String[] brokerCommand = _brokerCommandHelper.getBrokerCommand(1, "configFile", "json", logConfigFile); + + String[] expected = { "qpid", "-p", "1", "-sp", "configFile", "-st", "json" }; + assertEquals("Unexpected broker command", 7, brokerCommand.length); + for (int i = 0; i < expected.length; i++) + { + assertEquals("Unexpected command part value at " + i,expected[i], brokerCommand[i] ); + } + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java b/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java index a71a4ef517..8bad73d0ea 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/InternalBrokerHolder.java @@ -20,9 +20,6 @@ */ package org.apache.qpid.test.utils; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; import java.util.Set; import org.apache.log4j.Logger; @@ -82,28 +79,7 @@ public class InternalBrokerHolder implements BrokerHolder @Override public String dumpThreads() { - ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); - ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true); - StringBuilder dump = new StringBuilder(); - dump.append(String.format("%n")); - for (ThreadInfo threadInfo : threadInfos) - { - dump.append(threadInfo); - } - - long[] deadLocks = threadMXBean.findDeadlockedThreads(); - if (deadLocks != null && deadLocks.length > 0) - { - ThreadInfo[] deadlockedThreads = threadMXBean.getThreadInfo(deadLocks); - dump.append(String.format("%n")); - dump.append("Deadlock is detected!"); - dump.append(String.format("%n")); - for (ThreadInfo threadInfo : deadlockedThreads) - { - dump.append(threadInfo); - } - } - return dump.toString(); + return TestUtils.dumpThreads(); } @Override diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java index 43b80b45fb..6e6e3271f0 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/JMXTestUtils.java @@ -24,7 +24,6 @@ import junit.framework.TestCase; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.management.common.JMXConnnectionFactory; -import org.apache.qpid.management.common.mbeans.ConfigurationManagement; import org.apache.qpid.management.common.mbeans.LoggingManagement; import org.apache.qpid.management.common.mbeans.ManagedBroker; import org.apache.qpid.management.common.mbeans.ManagedConnection; @@ -32,6 +31,8 @@ import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.management.common.mbeans.ManagedQueue; import org.apache.qpid.management.common.mbeans.ServerInformation; import org.apache.qpid.management.common.mbeans.UserManagement; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.plugin.PluginFactory; import javax.management.InstanceNotFoundException; import javax.management.JMException; @@ -46,7 +47,9 @@ import javax.management.ObjectName; import javax.management.remote.JMXConnector; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -78,7 +81,7 @@ public class JMXTestUtils public void setUp() throws IOException, ConfigurationException, Exception { - _test.setConfigurationProperty("management.enabled", "true"); + _test.getBrokerConfiguration().addJmxManagementConfiguration(); } public void open() throws Exception @@ -287,9 +290,7 @@ public class JMXTestUtils public ObjectName getQueueObjectName(String virtualHostName, String queue) { // Get the name of the test manager - String query = "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" - + ObjectName.quote(virtualHostName) + ",name=" - + ObjectName.quote(queue) + ",*"; + String query = getQueueObjectNameString(virtualHostName, queue); Set objectNames = queryObjects(query); @@ -302,32 +303,20 @@ public class JMXTestUtils return objectName; } + public String getQueueObjectNameString(String virtualHostName, String queue) { + return "org.apache.qpid:type=VirtualHost.Queue,VirtualHost=" + + ObjectName.quote(virtualHostName) + ",name=" + + ObjectName.quote(queue) + ",*"; + } + /** - * Retrive the ObjectName for the given Exchange on a VirtualHost. - * - * This is then used to create a proxy to the ManagedExchange MBean. - * - * @param virtualHostName the VirtualHost the Exchange is on - * @param exchange the Exchange to retireve e.g. 'direct' - * @return the ObjectName for the given Exchange on the VirtualHost + * Generate the ObjectName for the given Exchange on a VirtualHost. */ - @SuppressWarnings("static-access") - public ObjectName getExchangeObjectName(String virtualHostName, String exchange) + public String getExchangeObjectName(String virtualHostName, String exchange) { - // Get the name of the test manager - String query = "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + return "org.apache.qpid:type=VirtualHost.Exchange,VirtualHost=" + ObjectName.quote(virtualHostName) + ",name=" + ObjectName.quote(exchange) + ",*"; - - Set objectNames = queryObjects(query); - - _test.assertNotNull("Null ObjectName Set returned", objectNames); - _test.assertEquals("Incorrect number of exchange with name '" + exchange + "' returned", 1, objectNames.size()); - - // We have verified we have only one value in objectNames so return it - ObjectName objectName = objectNames.iterator().next(); - _test.getLogger().info("Loading: " + objectName); - return objectName; } @SuppressWarnings("static-access") @@ -343,7 +332,7 @@ public class JMXTestUtils return getManagedObject(managedClass, objectName); } - public boolean isManagedObjectExist(String query) + public boolean doesManagedObjectExist(String query) { return !queryObjects(query).isEmpty(); } @@ -373,9 +362,20 @@ public class JMXTestUtils return getManagedObject(ManagedBroker.class, getVirtualHostManagerObjectName(virtualHost)); } + @SuppressWarnings("static-access") public ManagedExchange getManagedExchange(String exchangeName) { - ObjectName objectName = getExchangeObjectName("test", exchangeName); + String query = getExchangeObjectName("test", exchangeName); + + Set objectNames = queryObjects(query); + + _test.assertNotNull("Null ObjectName Set returned", objectNames); + _test.assertEquals("Incorrect number of exchange with name '" + exchangeName + "' returned", 1, objectNames.size()); + + // We have verified we have only one value in objectNames so return an mbean proxy for it + ObjectName objectName = objectNames.iterator().next(); + _test.getLogger().info("Loading: " + objectName); + return MBeanServerInvocationHandler.newProxyInstance(_mbsc, objectName, ManagedExchange.class, false); } @@ -391,12 +391,6 @@ public class JMXTestUtils return getManagedObject(LoggingManagement.class, objectName); } - public ConfigurationManagement getConfigurationManagement() throws MalformedObjectNameException - { - ObjectName objectName = new ObjectName("org.apache.qpid:type=ConfigurationManagement,name=ConfigurationManagement"); - return getManagedObject(ConfigurationManagement.class, objectName); - } - public UserManagement getUserManagement() throws MalformedObjectNameException { ObjectName objectName = new ObjectName("org.apache.qpid:type=UserManagement,name=UserManagement"); diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java old mode 100644 new mode 100755 index aa909a6674..d36f57171f --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -19,18 +19,17 @@ package org.apache.qpid.test.utils; import java.io.File; import java.io.FileOutputStream; -import java.io.IOException; import java.io.PrintStream; -import java.net.MalformedURLException; -import java.net.URL; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; - import javax.jms.BytesMessage; import javax.jms.Connection; import javax.jms.Destination; @@ -45,32 +44,34 @@ import javax.jms.Session; import javax.jms.StreamMessage; import javax.jms.TextMessage; import javax.jms.Topic; +import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; - import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnectionFactory; +import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQTopic; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionURL; -import org.apache.qpid.management.common.mbeans.ConfigurationManagement; import org.apache.qpid.server.Broker; import org.apache.qpid.server.BrokerOptions; -import org.apache.qpid.server.ProtocolExclusion; -import org.apache.qpid.server.ProtocolInclusion; -import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.BrokerProperties; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.MessageStoreConstants; +import org.apache.qpid.server.store.MessageStoreCreator; +import org.apache.qpid.server.store.MessageStoreFactory; import org.apache.qpid.server.store.derby.DerbyMessageStore; import org.apache.qpid.url.URLSyntaxException; import org.apache.qpid.util.FileUtils; -import org.apache.qpid.util.LogMonitor; /** * Qpid base class for system testing test cases. @@ -80,7 +81,7 @@ public class QpidBrokerTestCase extends QpidTestCase public enum BrokerType { EXTERNAL /** Test case relies on a Broker started independently of the test-suite */, - INTERNAL /** Test case starts an embedded broker within this JVM */, + INTERNAL /** Test case starts an embedded broker within this JVM */, SPAWNED /** Test case spawns a new broker as a separate process */ } @@ -88,9 +89,9 @@ public class QpidBrokerTestCase extends QpidTestCase public static final String GUEST_PASSWORD = "guest"; protected final static String QpidHome = System.getProperty("QPID_HOME"); - protected File _configFile = new File(System.getProperty("broker.config")); - protected File _logConfigFile = new File(System.getProperty("log4j.configuration")); - + private final File _configFile = new File(System.getProperty("broker.config")); + private File _logConfigFile; + protected final String _brokerStoreType = System.getProperty("broker.config-store-type", "json"); protected static final Logger _logger = Logger.getLogger(QpidBrokerTestCase.class); protected static final int LOGMONITOR_TIMEOUT = 5000; @@ -98,7 +99,7 @@ public class QpidBrokerTestCase extends QpidTestCase private Map _propertiesSetForBroker = new HashMap(); - private XMLConfiguration _testConfiguration = new XMLConfiguration(); + private Map _brokerConfigurations; private XMLConfiguration _testVirtualhosts = new XMLConfiguration(); protected static final String INDEX = "index"; @@ -106,24 +107,31 @@ public class QpidBrokerTestCase extends QpidTestCase private static final String DEFAULT_INITIAL_CONTEXT = "org.apache.qpid.jndi.PropertiesFileInitialContextFactory"; + private static Map supportedStoresClassToTypeMapping = new HashMap(); + static { - String initialContext = System.getProperty(InitialContext.INITIAL_CONTEXT_FACTORY); + String initialContext = System.getProperty(Context.INITIAL_CONTEXT_FACTORY); if (initialContext == null || initialContext.length() == 0) { - System.setProperty(InitialContext.INITIAL_CONTEXT_FACTORY, DEFAULT_INITIAL_CONTEXT); + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, DEFAULT_INITIAL_CONTEXT); + } + + MessageStoreCreator messageStoreCreator = new MessageStoreCreator(); + Collection factories = messageStoreCreator.getFactories(); + for (MessageStoreFactory messageStoreFactory : factories) + { + supportedStoresClassToTypeMapping.put(messageStoreFactory.createMessageStore().getClass().getName(), messageStoreFactory.getType()); } } // system properties private static final String TEST_VIRTUALHOSTS = "test.virtualhosts"; - private static final String TEST_CONFIG = "test.config"; private static final String BROKER_LANGUAGE = "broker.language"; protected static final String BROKER_TYPE = "broker.type"; private static final String BROKER_COMMAND = "broker.command"; private static final String BROKER_CLEAN_BETWEEN_TESTS = "broker.clean.between.tests"; - private static final String BROKER_EXISTING_QPID_WORK = "broker.existing.qpid.work"; private static final String BROKER_VERSION = "broker.version"; protected static final String BROKER_READY = "broker.ready"; private static final String BROKER_STOPPED = "broker.stopped"; @@ -131,8 +139,14 @@ public class QpidBrokerTestCase extends QpidTestCase private static final String BROKER_LOG_INTERLEAVE = "broker.log.interleave"; private static final String BROKER_LOG_PREFIX = "broker.log.prefix"; private static final String BROKER_PERSITENT = "broker.persistent"; - public static final String BROKER_PROTOCOL_EXCLUDES = "broker.protocol.excludes"; - public static final String BROKER_PROTOCOL_INCLUDES = "broker.protocol.includes"; + public static final String PROFILE_USE_SSL = "profile.use_ssl"; + + public static final int DEFAULT_PORT_VALUE = 5672; + public static final int DEFAULT_SSL_PORT_VALUE = 5671; + public static final int DEFAULT_JMXPORT_REGISTRYSERVER = 8999; + public static final int JMXPORT_CONNECTORSERVER_OFFSET = 100; + public static final int DEFAULT_HTTP_MANAGEMENT_PORT = 8080; + public static final int DEFAULT_HTTPS_MANAGEMENT_PORT = 8443; // values protected static final String JAVA = "java"; @@ -140,15 +154,15 @@ public class QpidBrokerTestCase extends QpidTestCase protected static final String QPID_HOME = "QPID_HOME"; - public static final int DEFAULT_VM_PORT = 1; - public static final int DEFAULT_PORT = Integer.getInteger("test.port", ServerConfiguration.DEFAULT_PORT); + public static final int DEFAULT_PORT = Integer.getInteger("test.port", DEFAULT_PORT_VALUE); public static final int FAILING_PORT = Integer.parseInt(System.getProperty("test.port.alt")); - public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", ServerConfiguration.DEFAULT_JMXPORT_REGISTRYSERVER); - public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.port.ssl", ServerConfiguration.DEFAULT_SSL_PORT); + public static final int DEFAULT_MANAGEMENT_PORT = Integer.getInteger("test.mport", DEFAULT_JMXPORT_REGISTRYSERVER); + public static final int DEFAULT_SSL_PORT = Integer.getInteger("test.port.ssl", DEFAULT_SSL_PORT_VALUE); protected String _brokerLanguage = System.getProperty(BROKER_LANGUAGE, JAVA); protected BrokerType _brokerType = BrokerType.valueOf(System.getProperty(BROKER_TYPE, "").toUpperCase()); - protected String _brokerCommand = System.getProperty(BROKER_COMMAND); + + protected BrokerCommandHelper _brokerCommandHelper = new BrokerCommandHelper(System.getProperty(BROKER_COMMAND)); private Boolean _brokerCleanBetweenTests = Boolean.getBoolean(BROKER_CLEAN_BETWEEN_TESTS); private final AmqpProtocolVersion _brokerVersion = AmqpProtocolVersion.valueOf(System.getProperty(BROKER_VERSION, "")); protected String _output = System.getProperty(TEST_OUTPUT, System.getProperty("java.io.tmpdir")); @@ -190,14 +204,67 @@ public class QpidBrokerTestCase extends QpidTestCase } private MessageType _messageType = MessageType.TEXT; - public QpidBrokerTestCase(String name) - { - super(name); - } - public QpidBrokerTestCase() { super(); + _brokerConfigurations = new HashMap(); + initialiseLogConfigFile(); + } + + public TestBrokerConfiguration getBrokerConfiguration(int port) + { + int actualPort = getPort(port); + + synchronized (_brokerConfigurations) + { + TestBrokerConfiguration configuration = _brokerConfigurations.get(actualPort); + if (configuration == null) + { + configuration = createBrokerConfiguration(actualPort); + } + return configuration; + } + } + + public TestBrokerConfiguration getBrokerConfiguration() + { + return getBrokerConfiguration(DEFAULT_PORT); + } + + public TestBrokerConfiguration createBrokerConfiguration(int port) + { + int actualPort = getPort(port); + TestBrokerConfiguration configuration = new TestBrokerConfiguration(System.getProperty(_brokerStoreType), _configFile.getAbsolutePath()); + synchronized (_brokerConfigurations) + { + _brokerConfigurations.put(actualPort, configuration); + } + if (actualPort != DEFAULT_PORT) + { + configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT, Port.PORT, actualPort); + configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_RMI_PORT, Port.PORT, getManagementPort(actualPort)); + configuration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_JMX_PORT, Port.PORT, getManagementPort(actualPort) + JMXPORT_CONNECTORSERVER_OFFSET); + } + return configuration; + } + + private void initialiseLogConfigFile() + { + try + { + _logger.info("About to initialise log config file from system property: " + LOG4J_CONFIG_FILE_PATH); + + URI uri = new URI("file", LOG4J_CONFIG_FILE_PATH, null); + _logConfigFile = new File(uri); + if(!_logConfigFile.exists()) + { + throw new RuntimeException("Log config file " + _logConfigFile.getAbsolutePath() + " does not exist"); + } + } + catch (URISyntaxException e) + { + throw new RuntimeException("Couldn't create URI from log4.configuration: " + LOG4J_CONFIG_FILE_PATH, e); + } } public Logger getLogger() @@ -289,16 +356,6 @@ public class QpidBrokerTestCase extends QpidTestCase fail("Unable to test without config file:" + _configFile); } - String existingQpidWorkPath = System.getProperty(BROKER_EXISTING_QPID_WORK); - if(existingQpidWorkPath != null && !existingQpidWorkPath.equals("")) - { - - String qpidWork = getQpidWork(_brokerType, getPort()); - File existing = new File(existingQpidWorkPath); - cleanBrokerWork(qpidWork); - FileUtils.copyRecursive(existing, new File(qpidWork)); - } - startBroker(); } @@ -322,7 +379,7 @@ public class QpidBrokerTestCase extends QpidTestCase { Set ports = new HashSet(); int managementPort = getManagementPort(mainPort); - int connectorServerPort = managementPort + ServerConfiguration.JMXPORT_CONNECTORSERVER_OFFSET; + int connectorServerPort = managementPort + JMXPORT_CONNECTORSERVER_OFFSET; ports.add(mainPort); ports.add(managementPort); @@ -354,37 +411,33 @@ public class QpidBrokerTestCase extends QpidTestCase } } - protected String getBrokerCommand(int port) throws MalformedURLException + public void startBroker() throws Exception { - final int sslPort = port-1; - final String protocolExcludesList = getProtocolExcludesList(port, sslPort); - final String protocolIncludesList = getProtocolIncludesList(port, sslPort); + startBroker(0); + } - return _brokerCommand - .replace("@PORT", "" + port) - .replace("@SSL_PORT", "" + sslPort) - .replace("@MPORT", "" + getManagementPort(port)) - .replace("@CONFIG_FILE", _configFile.toString()) - .replace("@LOG_CONFIG_FILE", _logConfigFile.toString()) - .replace("@EXCLUDES", protocolExcludesList) - .replace("@INCLUDES", protocolIncludesList); + public void startBroker(int port) throws Exception + { + int actualPort = getPort(port); + TestBrokerConfiguration configuration = getBrokerConfiguration(actualPort); + startBroker(actualPort, configuration, _testVirtualhosts); } - public void startBroker() throws Exception + + protected File getBrokerCommandLog4JFile() { - startBroker(0); + return _logConfigFile; } - public void startBroker(int port) throws Exception + protected void setBrokerCommandLog4JFile(File file) { - startBroker(port, _testConfiguration, _testVirtualhosts); + _logConfigFile = file; + _logger.info("Modified log config file to: " + file); } - public void startBroker(int port, XMLConfiguration testConfiguration, XMLConfiguration virtualHosts) throws Exception + public void startBroker(int port, TestBrokerConfiguration testConfiguration, XMLConfiguration virtualHosts) throws Exception { port = getPort(port); - - // Save any configuration changes that have been made String testConfig = saveTestConfiguration(port, testConfiguration); String virtualHostsConfig = saveTestVirtualhosts(port, virtualHosts); @@ -397,28 +450,20 @@ public class QpidBrokerTestCase extends QpidTestCase if (_brokerType.equals(BrokerType.INTERNAL) && !existingInternalBroker()) { - setConfigurationProperty(ServerConfiguration.MGMT_CUSTOM_REGISTRY_SOCKET, String.valueOf(false)); - testConfig = saveTestConfiguration(port, testConfiguration); - _logger.info("Set test.config property to: " + testConfig); _logger.info("Set test.virtualhosts property to: " + virtualHostsConfig); - setSystemProperty(TEST_CONFIG, testConfig); setSystemProperty(TEST_VIRTUALHOSTS, virtualHostsConfig); - + setSystemProperty(BrokerProperties.PROPERTY_USE_CUSTOM_RMI_SOCKET_FACTORY, "false"); BrokerOptions options = new BrokerOptions(); - options.setConfigFile(_configFile.getAbsolutePath()); - options.addPort(port); - - addExcludedPorts(port, DEFAULT_SSL_PORT, options); - addIncludedPorts(port, DEFAULT_SSL_PORT, options); - options.setJmxPortRegistryServer(getManagementPort(port)); + options.setConfigurationStoreType(_brokerStoreType); + options.setConfigurationStoreLocation(testConfig); //Set the log config file, relying on the log4j.configuration system property //set on the JVM by the JUnit runner task in module.xml. options.setLogConfigFile(_logConfigFile.getAbsolutePath()); Broker broker = new Broker(); - _logger.info("starting internal broker (same JVM)"); + _logger.info("Starting internal broker (same JVM)"); broker.startup(options); _brokers.put(port, new InternalBrokerHolder(broker, System.getProperty("QPID_WORK"), portsUsedByBroker)); @@ -427,9 +472,10 @@ public class QpidBrokerTestCase extends QpidTestCase { // Add the port to QPID_WORK to ensure unique working dirs for multi broker tests final String qpidWork = getQpidWork(_brokerType, port); - String cmd = getBrokerCommand(port); - _logger.info("starting external broker: " + cmd); - ProcessBuilder pb = new ProcessBuilder(cmd.split("\\s+")); + + String[] cmd = _brokerCommandHelper.getBrokerCommand(port, testConfig, _brokerStoreType, _logConfigFile); + _logger.info("Starting spawn broker using command: " + StringUtils.join(cmd, ' ')); + ProcessBuilder pb = new ProcessBuilder(cmd); pb.redirectErrorStream(true); Map processEnv = pb.environment(); String qpidHome = System.getProperty(QPID_HOME); @@ -459,28 +505,28 @@ public class QpidBrokerTestCase extends QpidTestCase } } + String qpidOpts = ""; - // Add default test logging levels that are used by the log4j-test - // Use the convenience methods to push the current logging setting - // in to the external broker's QPID_OPTS string. - if (System.getProperty("amqj.protocol.logging.level") != null) + // a synchronized hack to avoid adding into QPID_OPTS the values + // of JVM properties "test.virtualhosts" and "test.config" set by a concurrent startup process + synchronized (_propertiesSetForBroker) { + // Add default test logging levels that are used by the log4j-test + // Use the convenience methods to push the current logging setting + // in to the external broker's QPID_OPTS string. setSystemProperty("amqj.protocol.logging.level"); - } - if (System.getProperty("root.logging.level") != null) - { setSystemProperty("root.logging.level"); - } - - // set test.config and test.virtualhosts - String qpidOpts = " -D" + TEST_CONFIG + "=" + testConfig + " -D" + TEST_VIRTUALHOSTS + "=" + virtualHostsConfig; + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_EXCLUDES); + setSystemProperty(BrokerProperties.PROPERTY_BROKER_DEFAULT_AMQP_PROTOCOL_INCLUDES); + setSystemProperty(TEST_VIRTUALHOSTS, virtualHostsConfig); - // Add all the specified system properties to QPID_OPTS - if (!_propertiesSetForBroker.isEmpty()) - { - for (String key : _propertiesSetForBroker.keySet()) + // Add all the specified system properties to QPID_OPTS + if (!_propertiesSetForBroker.isEmpty()) { - qpidOpts += " -D" + key + "=" + _propertiesSetForBroker.get(key); + for (String key : _propertiesSetForBroker.keySet()) + { + qpidOpts += " -D" + key + "=" + _propertiesSetForBroker.get(key); + } } } if (processEnv.containsKey("QPID_OPTS")) @@ -489,9 +535,6 @@ public class QpidBrokerTestCase extends QpidTestCase } processEnv.put("QPID_OPTS", qpidOpts); - _logger.info("Set test.config property to: " + testConfig); - _logger.info("Set test.virtualhosts property to: " + virtualHostsConfig); - // cpp broker requires that the work directory is created createBrokerWork(qpidWork); @@ -505,9 +548,15 @@ public class QpidBrokerTestCase extends QpidTestCase p.start(); + SpawnedBrokerHolder holder = new SpawnedBrokerHolder(process, qpidWork, portsUsedByBroker); if (!p.await(30, TimeUnit.SECONDS)) { _logger.info("broker failed to become ready (" + p.getReady() + "):" + p.getStopLine()); + String threadDump = holder.dumpThreads(); + if (!threadDump.isEmpty()) + { + _logger.info("the result of a try to capture thread dump:" + threadDump); + } //Ensure broker has stopped process.destroy(); cleanBrokerWork(qpidWork); @@ -528,65 +577,7 @@ public class QpidBrokerTestCase extends QpidTestCase // this is expect if the broker started successfully } - _brokers.put(port, new SpawnedBrokerHolder(process, qpidWork, portsUsedByBroker)); - } - } - - private void addExcludedPorts(int port, int sslPort, BrokerOptions options) - { - final String protocolExcludesList = getProtocolExcludesList(port, sslPort); - - if (protocolExcludesList.equals("")) - { - return; - } - final String[] toks = protocolExcludesList.split("\\s"); - - if(toks.length % 2 != 0) - { - throw new IllegalArgumentException("Must be an even number of tokens in '" + protocolExcludesList + "'"); - } - for (int i = 0; i < toks.length; i=i+2) - { - String excludeArg = toks[i]; - final int excludedPort = Integer.parseInt(toks[i+1]); - options.addExcludedPort(ProtocolExclusion.lookup(excludeArg), excludedPort); - - _logger.info("Adding protocol exclusion " + excludeArg + " " + excludedPort); - } - } - - protected String getProtocolExcludesList(int port, int sslPort) - { - return System.getProperty(BROKER_PROTOCOL_EXCLUDES,"").replace("@PORT", "" + port).replace("@SSL_PORT", "" + sslPort); - } - - private String getProtocolIncludesList(int port, int sslPort) - { - return System.getProperty(BROKER_PROTOCOL_INCLUDES, "").replace("@PORT", "" + port).replace("@SSL_PORT", "" + sslPort); - } - - private void addIncludedPorts(int port, int sslPort, BrokerOptions options) - { - final String protocolIncludesList = getProtocolIncludesList(port, sslPort); - - if (protocolIncludesList.equals("")) - { - return; - } - final String[] toks = protocolIncludesList.split("\\s"); - - if(toks.length % 2 != 0) - { - throw new IllegalArgumentException("Must be an even number of tokens in '" + protocolIncludesList + "'"); - } - for (int i = 0; i < toks.length; i=i+2) - { - String includeArg = toks[i]; - final int includedPort = Integer.parseInt(toks[i+1]); - options.addIncludedPort(ProtocolInclusion.lookup(includeArg), includedPort); - - _logger.info("Adding protocol inclusion " + includeArg + " " + includedPort); + _brokers.put(port, holder); } } @@ -620,7 +611,7 @@ public class QpidBrokerTestCase extends QpidTestCase public String getTestConfigFile(int port) { - return _output + "/" + getTestQueueName() + "-" + port + "-config.xml"; + return _output + "/" + getTestQueueName() + "-" + port + "-config"; } public String getTestVirtualhostsFile(int port) @@ -633,44 +624,33 @@ public class QpidBrokerTestCase extends QpidTestCase return file.replace(System.getProperty(QPID_HOME,"QPID_HOME") + "/",""); } - protected void saveTestConfiguration() throws ConfigurationException + protected String getPathRelativeToWorkingDirectory(String file) { - String relative = saveTestConfiguration(getPort(), _testConfiguration); - _logger.info("Set test.config property to: " + relative); - setSystemProperty(TEST_CONFIG, relative); + File configLocation = new File(file); + File workingDirectory = new File(System.getProperty("user.dir")); + return configLocation.getAbsolutePath().replace(workingDirectory.getAbsolutePath(), "").substring(1); } - protected String saveTestConfiguration(int port, XMLConfiguration testConfiguration) throws ConfigurationException + protected String saveTestConfiguration(int port, TestBrokerConfiguration testConfiguration) { - // Specify the test config file String testConfig = getTestConfigFile(port); - String relative = relativeToQpidHome(testConfig); - - _logger.info("Saving test virtualhosts file at: " + testConfig); - - // Create the file if configuration does not exist - if (testConfiguration.isEmpty()) + String relative = getPathRelativeToWorkingDirectory(testConfig); + if (!testConfiguration.isSaved()) { - testConfiguration.addProperty("__ignore", "true"); + _logger.info("Saving test broker configuration at: " + testConfig); + testConfiguration.save(new File(testConfig)); + testConfiguration.setSaved(true); } - testConfiguration.save(testConfig); return relative; } - protected void saveTestVirtualhosts() throws ConfigurationException - { - String relative = saveTestVirtualhosts(getPort(), _testVirtualhosts); - _logger.info("Set test.virtualhosts property to: " + relative); - setSystemProperty(TEST_VIRTUALHOSTS, relative); - } - protected String saveTestVirtualhosts(int port, XMLConfiguration virtualHostConfiguration) throws ConfigurationException { // Specify the test virtualhosts file String testVirtualhosts = getTestVirtualhostsFile(port); String relative = relativeToQpidHome(testVirtualhosts); - _logger.info("Set test.virtualhosts property to: " + testVirtualhosts); + _logger.info("Path to virtualhosts configuration: " + testVirtualhosts); // Create the file if configuration does not exist if (virtualHostConfiguration.isEmpty()) @@ -818,57 +798,41 @@ public class QpidBrokerTestCase extends QpidTestCase } /** - * Attempt to set the Java Broker to use the BDBMessageStore for persistence - * Falling back to the DerbyMessageStore if - * - * @param virtualhost - The virtualhost to modify + * Creates a new virtual host within the test virtualhost file. + * @param brokerPort broker port + * @param virtualHostName virtual host name * - * @throws ConfigurationException - when reading/writing existing configuration - * @throws IOException - When creating a temporary file. + * @throws ConfigurationException */ - protected void makeVirtualHostPersistent(String virtualhost) - throws ConfigurationException, IOException + protected void createTestVirtualHost(int brokerPort, String virtualHostName) throws ConfigurationException { - Class storeClass = null; - try + String storeClassName = getTestProfileMessageStoreClassName(); + + _testVirtualhosts.setProperty("virtualhost.name(-1)", virtualHostName); + _testVirtualhosts.setProperty("virtualhost." + virtualHostName + ".store.class", storeClassName); + + String storeDir = null; + + if (System.getProperty("profile", "").startsWith("java-dby-mem")) { - // Try and lookup the BDB class - storeClass = Class.forName("org.apache.qpid.server.store.berkeleydb.BDBMessageStore"); + storeDir = DerbyMessageStore.MEMORY_STORE_LOCATION; } - catch (ClassNotFoundException e) + else if (!MEMORY_STORE_CLASS_NAME.equals(storeClassName)) { - // No BDB store, we'll use Derby instead. - storeClass = DerbyMessageStore.class; + storeDir = "${QPID_WORK}" + File.separator + virtualHostName + "-store"; } + if (storeDir != null) + { + _testVirtualhosts.setProperty("virtualhost." + virtualHostName + ".store." + MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, storeDir); + } - setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store.class", - storeClass.getName()); - setConfigurationProperty("virtualhosts.virtualhost." + virtualhost + ".store." + MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, - "${QPID_WORK}/" + virtualhost); - } - - /** - * Get a property value from the current configuration file. - * - * @param property the property to lookup - * - * @return the requested String Value - * - * @throws org.apache.commons.configuration.ConfigurationException - * - */ - protected String getConfigurationStringProperty(String property) throws ConfigurationException - { - // Call save Configuration to be sure we have saved the test specific - // file. As the optional status - saveTestConfiguration(); - saveTestVirtualhosts(); - - ServerConfiguration configuration = new ServerConfiguration(_configFile); - // Don't need to configuration.configure() here as we are just pulling - // values directly by String. - return configuration.getConfig().getString(property); + // add new virtual host configuration to the broker store + Map attributes = new HashMap(); + attributes.put(VirtualHost.NAME, virtualHostName); + attributes.put(VirtualHost.CONFIG_PATH, System.getProperty("broker.virtualhosts-config")); + int port = getPort(brokerPort); + getBrokerConfiguration(port).addHostConfiguration(attributes); } /** @@ -884,10 +848,8 @@ public class QpidBrokerTestCase extends QpidTestCase * @param value the new value * * @throws ConfigurationException when loading the current config file - * @throws IOException when writing the new config file */ - public void setConfigurationProperty(String property, String value) - throws ConfigurationException, IOException + public void setVirtualHostConfigurationProperty(String property, String value) throws ConfigurationException { // Choose which file to write the property to based on prefix. if (property.startsWith("virtualhosts")) @@ -896,7 +858,7 @@ public class QpidBrokerTestCase extends QpidTestCase } else { - _testConfiguration.setProperty(property, value); + throw new ConfigurationException("Cannot set broker configuration as property"); } } @@ -914,11 +876,13 @@ public class QpidBrokerTestCase extends QpidTestCase */ protected void setBrokerOnlySystemProperty(String property, String value) { - if (!_propertiesSetForBroker.containsKey(property)) + synchronized (_propertiesSetForBroker) { - _propertiesSetForBroker.put(property, value); + if (!_propertiesSetForBroker.containsKey(property)) + { + _propertiesSetForBroker.put(property, value); + } } - } /** @@ -931,7 +895,11 @@ public class QpidBrokerTestCase extends QpidTestCase */ protected void setSystemProperty(String property) { - setSystemProperty(property, System.getProperty(property)); + String value = System.getProperty(property); + if (value != null) + { + setSystemProperty(property, value); + } } /** @@ -939,7 +907,7 @@ public class QpidBrokerTestCase extends QpidTestCase * * When the test run is complete the value will be reverted. * - * The values set using this method will also be propogated to the external + * The values set using this method will also be propagated to the external * Java Broker via a -D value defined in QPID_OPTS. * * If the value should not be set on the broker then use @@ -950,9 +918,18 @@ public class QpidBrokerTestCase extends QpidTestCase */ protected void setSystemProperty(String property, String value) { - // Record the value for the external broker - _propertiesSetForBroker.put(property, value); - + synchronized(_propertiesSetForBroker) + { + // Record the value for the external broker + if (value == null) + { + _propertiesSetForBroker.remove(property); + } + else + { + _propertiesSetForBroker.put(property, value); + } + } //Set the value for the test client vm aswell. setTestClientSystemProperty(property, value); } @@ -1073,7 +1050,7 @@ public class QpidBrokerTestCase extends QpidTestCase _logger.info("get ConnectionFactory"); if (_connectionFactory == null) { - if (Boolean.getBoolean("profile.use_ssl")) + if (Boolean.getBoolean(PROFILE_USE_SSL)) { _connectionFactory = getConnectionFactory("default.ssl"); } @@ -1092,7 +1069,7 @@ public class QpidBrokerTestCase extends QpidTestCase * * @return A connection factory * - * @throws Exception if there is an error getting the tactory + * @throws Exception if there is an error getting the factory */ public AMQConnectionFactory getConnectionFactory(String factoryName) throws NamingException { @@ -1104,6 +1081,22 @@ public class QpidBrokerTestCase extends QpidTestCase return getConnection(GUEST_USERNAME, GUEST_PASSWORD); } + public Connection getConnectionWithOptions(Map options) + throws URLSyntaxException, NamingException, JMSException + { + ConnectionURL curl = new AMQConnectionURL(getConnectionFactory().getConnectionURLString()); + for(Map.Entry entry : options.entrySet()) + { + curl.setOption(entry.getKey(), entry.getValue()); + } + curl = new AMQConnectionURL(curl.toString()); + + curl.setUsername(GUEST_USERNAME); + curl.setPassword(GUEST_PASSWORD); + return getConnection(curl); + } + + public Connection getConnection(ConnectionURL url) throws JMSException { _logger.info(url.getURL()); @@ -1363,11 +1356,6 @@ public class QpidBrokerTestCase extends QpidTestCase _messageSize = byteSize; } - public ConnectionURL getConnectionURL() throws NamingException - { - return getConnectionFactory().getConnectionURL(); - } - public BrokerDetails getBroker() { try @@ -1390,31 +1378,6 @@ public class QpidBrokerTestCase extends QpidTestCase return null; } - /** - * Reloads the broker security configuration using the ApplicationRegistry (InVM brokers) or the - * ConfigurationManagementMBean via the JMX interface (Standalone brokers, management must be - * enabled before calling the method). - */ - public void reloadBrokerSecurityConfig() throws Exception - { - JMXTestUtils jmxu = new JMXTestUtils(this); - jmxu.open(); - - try - { - ConfigurationManagement configMBean = jmxu.getConfigurationManagement(); - configMBean.reloadSecurityConfiguration(); - } - finally - { - jmxu.close(); - } - - LogMonitor _monitor = new LogMonitor(_outputFile); - assertTrue("The expected server security configuration reload did not occur", - _monitor.waitForMessage(ServerConfiguration.SECURITY_CONFIG_RELOADED, LOGMONITOR_TIMEOUT)); - } - protected int getFailingPort() { return FAILING_PORT; @@ -1430,13 +1393,14 @@ public class QpidBrokerTestCase extends QpidTestCase _testVirtualhosts = testVirtualhosts; } - public XMLConfiguration getTestConfiguration() + public String getTestProfileMessageStoreType() { - return _testConfiguration; + final String storeClass = getTestProfileMessageStoreClassName(); + if (storeClass == null) + { + return MemoryMessageStore.TYPE; + } + return supportedStoresClassToTypeMapping.get(storeClass); } - public void setTestConfiguration(XMLConfiguration testConfiguration) - { - _testConfiguration = testConfiguration; - } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java deleted file mode 100644 index 72003ed7d7..0000000000 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidClientConnectionHelper.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.qpid.test.utils; - -import org.apache.log4j.Logger; - -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQConnectionFactory; -import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.client.JMSAMQException; -import org.apache.qpid.url.URLSyntaxException; - -import javax.jms.Connection; -import javax.jms.ExceptionListener; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.jms.TextMessage; - -/** - * @todo This was originally cut and paste from the client module leading to a duplicate class, then altered very - * slightly. To avoid the duplicate class the name was altered slightly to have 'Helper' on the end in order - * to distinguish it from the original. Delete this class and use the original instead, just upgrade it to - * provide the new features needed. - */ -public class QpidClientConnectionHelper implements ExceptionListener -{ - - private static final Logger _logger = Logger.getLogger(QpidClientConnectionHelper.class); - - private boolean transacted = true; - private int ackMode = Session.CLIENT_ACKNOWLEDGE; - private Connection connection; - - private String virtualHost; - private String brokerlist; - private int prefetch; - protected Session session; - protected boolean connected; - - public QpidClientConnectionHelper(String broker) - { - super(); - setVirtualHost("/test"); - setBrokerList(broker); - setPrefetch(5000); - } - - public void connect() throws JMSException - { - if (!connected) - { - /* - * amqp://[user:pass@][clientid]/virtualhost? - * brokerlist='[transport://]host[:port][?option='value'[&option='value']];' - * [&failover='method[?option='value'[&option='value']]'] - * [&option='value']" - */ - String brokerUrl = "amqp://guest:guest@" + virtualHost + "?brokerlist='" + brokerlist + "'"; - try - { - AMQConnectionFactory factory = new AMQConnectionFactory(new AMQConnectionURL(brokerUrl)); - _logger.info("connecting to Qpid :" + brokerUrl); - connection = factory.createConnection(); - - // register exception listener - connection.setExceptionListener(this); - - session = ((AMQConnection) connection).createSession(transacted, ackMode, prefetch); - - _logger.info("starting connection"); - connection.start(); - - connected = true; - } - catch (URLSyntaxException e) - { - throw new JMSAMQException("URL syntax error in [" + brokerUrl + "]: " + e.getMessage(), e); - } - } - } - - public void disconnect() throws JMSException - { - if (connected) - { - session.commit(); - session.close(); - connection.close(); - connected = false; - _logger.info("disconnected"); - } - } - - public void disconnectWithoutCommit() throws JMSException - { - if (connected) - { - session.close(); - connection.close(); - connected = false; - _logger.info("disconnected without commit"); - } - } - - public String getBrokerList() - { - return brokerlist; - } - - public void setBrokerList(String brokerlist) - { - this.brokerlist = brokerlist; - } - - public String getVirtualHost() - { - return virtualHost; - } - - public void setVirtualHost(String virtualHost) - { - this.virtualHost = virtualHost; - } - - public void setPrefetch(int prefetch) - { - this.prefetch = prefetch; - } - - /** override as necessary */ - public void onException(JMSException exception) - { - _logger.info("ExceptionListener event: error " + exception.getErrorCode() + ", message: " + exception.getMessage()); - } - - public boolean isConnected() - { - return connected; - } - - public Session getSession() - { - return session; - } - - /** - * Put a String as a text messages, repeat n times. A null payload will result in a null message. - * - * @param queueName The queue name to put to - * @param payload the content of the payload - * @param copies the number of messages to put - * - * @throws javax.jms.JMSException any exception that occurs - */ - public void put(String queueName, String payload, int copies, int deliveryMode) throws JMSException - { - if (!connected) - { - connect(); - } - - _logger.info("putting to queue " + queueName); - Queue queue = session.createQueue(queueName); - - final MessageProducer sender = session.createProducer(queue); - - sender.setDeliveryMode(deliveryMode); - - for (int i = 0; i < copies; i++) - { - Message m = session.createTextMessage(payload + i); - m.setIntProperty("index", i + 1); - sender.send(m); - } - - session.commit(); - sender.close(); - _logger.info("put " + copies + " copies"); - } - - /** - * GET the top message on a queue. Consumes the message. Accepts timeout value. - * - * @param queueName The quename to get from - * @param readTimeout The timeout to use - * - * @return the content of the text message if any - * - * @throws javax.jms.JMSException any exception that occured - */ - public Message getNextMessage(String queueName, long readTimeout) throws JMSException - { - if (!connected) - { - connect(); - } - - Queue queue = session.createQueue(queueName); - - final MessageConsumer consumer = session.createConsumer(queue); - - Message message = consumer.receive(readTimeout); - session.commit(); - consumer.close(); - - Message result; - - // all messages we consume should be TextMessages - if (message instanceof TextMessage) - { - result = ((TextMessage) message); - } - else if (null == message) - { - result = null; - } - else - { - _logger.info("warning: received non-text message"); - result = message; - } - - return result; - } - - /** - * GET the top message on a queue. Consumes the message. - * - * @param queueName The Queuename to get from - * - * @return The string content of the text message, if any received - * - * @throws javax.jms.JMSException any exception that occurs - */ - public Message getNextMessage(String queueName) throws JMSException - { - return getNextMessage(queueName, 0); - } - - /** - * Completely clears a queue. For readTimeout behaviour see Javadocs for javax.jms.MessageConsumer. - * - * @param queueName The Queue name to consume from - * @param readTimeout The timeout for each consume - * - * @throws javax.jms.JMSException Any exception that occurs during the consume - * @throws InterruptedException If the consume thread was interrupted during a consume. - */ - public void consume(String queueName, int readTimeout) throws JMSException, InterruptedException - { - if (!connected) - { - connect(); - } - - _logger.info("consuming queue " + queueName); - Queue queue = session.createQueue(queueName); - - final MessageConsumer consumer = session.createConsumer(queue); - int messagesReceived = 0; - - _logger.info("consuming..."); - while ((consumer.receive(readTimeout)) != null) - { - messagesReceived++; - } - - session.commit(); - consumer.close(); - _logger.info("consumed: " + messagesReceived); - } -} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java new file mode 100644 index 0000000000..80f8010678 --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java @@ -0,0 +1,219 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.test.utils; + +import java.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Plugin; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.plugin.PluginFactory; + +public class TestBrokerConfiguration +{ + public static final String ENTRY_NAME_HTTP_PORT = "http"; + public static final String ENTRY_NAME_AMQP_PORT = "amqp"; + public static final String ENTRY_NAME_RMI_PORT = "rmi"; + public static final String ENTRY_NAME_JMX_PORT = "jmx"; + public static final String ENTRY_NAME_VIRTUAL_HOST = "test"; + public static final String ENTRY_NAME_AUTHENTICATION_PROVIDER = "plain"; + public static final String ENTRY_NAME_EXTERNAL_PROVIDER = "external"; + public static final String ENTRY_NAME_SSL_PORT = "sslPort"; + public static final String ENTRY_NAME_HTTP_MANAGEMENT = "MANAGEMENT-HTTP"; + public static final String MANAGEMENT_HTTP_PLUGIN_TYPE = "MANAGEMENT-HTTP"; + public static final String ENTRY_NAME_JMX_MANAGEMENT = "MANAGEMENT-JMX"; + public static final String MANAGEMENT_JMX_PLUGIN_TYPE = "MANAGEMENT-JMX"; + public static final String ENTRY_NAME_ANONYMOUS_PROVIDER = "anonymous"; + + private JsonConfigurationEntryStore _store; + private boolean _saved; + + public TestBrokerConfiguration(String storeType, String intialStoreLocation) + { + // TODO: add support for DERBY store + _store = new JsonConfigurationEntryStore(); + _store.open(JsonConfigurationEntryStore.IN_MEMORY, intialStoreLocation); + } + + public boolean setBrokerAttribute(String name, Object value) + { + return setObjectAttribute(_store.getRootEntry(), name, value); + } + + public boolean setObjectAttribute(String objectName, String attributeName, Object value) + { + ConfigurationEntry entry = findObjectByName(objectName); + if (entry == null) + { + return false; + } + return setObjectAttribute(entry, attributeName, value); + } + + public boolean setObjectAttributes(String objectName, Map attributes) + { + ConfigurationEntry entry = findObjectByName(objectName); + if (entry == null) + { + return false; + } + return setObjectAttributes(entry, attributes); + } + + public boolean save(File configFile) + { + _store.copyTo(configFile.getAbsolutePath()); + return true; + } + + public UUID[] removeObjectConfiguration(String name) + { + ConfigurationEntry entry = findObjectByName(name); + if (entry != null) + { + return _store.remove(entry.getId()); + } + return null; + } + + public UUID addObjectConfiguration(String name, String type, Map attributes) + { + UUID id = UUIDGenerator.generateBrokerChildUUID(type, name); + addObjectConfiguration(id, type, attributes); + return id; + } + + public UUID addJmxManagementConfiguration() + { + Map attributes = new HashMap(); + attributes.put(PluginFactory.PLUGIN_TYPE, MANAGEMENT_JMX_PLUGIN_TYPE); + attributes.put(Plugin.NAME, ENTRY_NAME_JMX_MANAGEMENT); + return addObjectConfiguration(ENTRY_NAME_JMX_MANAGEMENT, Plugin.class.getSimpleName(), attributes); + } + + public UUID addHttpManagementConfiguration() + { + Map attributes = new HashMap(); + attributes.put(PluginFactory.PLUGIN_TYPE, MANAGEMENT_HTTP_PLUGIN_TYPE); + attributes.put(Plugin.NAME, ENTRY_NAME_HTTP_MANAGEMENT); + return addObjectConfiguration(ENTRY_NAME_HTTP_MANAGEMENT, Plugin.class.getSimpleName(), attributes); + } + + public UUID addPortConfiguration(Map attributes) + { + String name = (String) attributes.get(Port.NAME); + return addObjectConfiguration(name, Port.class.getSimpleName(), attributes); + } + + public UUID addHostConfiguration(Map attributes) + { + String name = (String) attributes.get(VirtualHost.NAME); + return addObjectConfiguration(name, VirtualHost.class.getSimpleName(), attributes); + } + + public UUID addAuthenticationProviderConfiguration(Map attributes) + { + String name = (String) attributes.get(AuthenticationProvider.NAME); + return addObjectConfiguration(name, AuthenticationProvider.class.getSimpleName(), attributes); + } + + private boolean setObjectAttributes(ConfigurationEntry entry, Map attributes) + { + Map newAttributes = new HashMap(entry.getAttributes()); + newAttributes.putAll(attributes); + ConfigurationEntry newEntry = new ConfigurationEntry(entry.getId(), entry.getType(), newAttributes, + entry.getChildrenIds(), _store); + _store.save(newEntry); + return true; + } + + private ConfigurationEntry findObjectByName(String objectName) + { + ConfigurationEntry root = _store.getRootEntry(); + return findObjectByName(root, objectName); + } + + private ConfigurationEntry findObjectByName(ConfigurationEntry entry, String objectName) + { + Map attributes = entry.getAttributes(); + if (attributes != null) + { + String name = (String) attributes.get("name"); + if (objectName.equals(name)) + { + return entry; + } + } + Set childrenIds = entry.getChildrenIds(); + for (UUID uuid : childrenIds) + { + ConfigurationEntry child = _store.getEntry(uuid); + ConfigurationEntry result = findObjectByName(child, objectName); + if (result != null) + { + return result; + } + } + return null; + } + + private void addObjectConfiguration(UUID id, String type, Map attributes) + { + ConfigurationEntry entry = new ConfigurationEntry(id, type, attributes, Collections. emptySet(), _store); + ConfigurationEntry root = _store.getRootEntry(); + Set childrenIds = new HashSet(root.getChildrenIds()); + childrenIds.add(id); + ConfigurationEntry newRoot = new ConfigurationEntry(root.getId(), root.getType(), root.getAttributes(), childrenIds, + _store); + _store.save(newRoot, entry); + } + + private boolean setObjectAttribute(ConfigurationEntry entry, String attributeName, Object value) + { + Map attributes = new HashMap(entry.getAttributes()); + attributes.put(attributeName, value); + ConfigurationEntry newEntry = new ConfigurationEntry(entry.getId(), entry.getType(), attributes, entry.getChildrenIds(), + _store); + _store.save(newEntry); + return true; + } + + public boolean isSaved() + { + return _saved; + } + + public void setSaved(boolean saved) + { + _saved = saved; + } + +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java new file mode 100644 index 0000000000..9d5be775dc --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestSSLConstants.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.test.utils; + +public interface TestSSLConstants +{ + String KEYSTORE = "test-profiles/test_resources/ssl/java_client_keystore.jks"; + String KEYSTORE_PASSWORD = "password"; + String TRUSTSTORE = "test-profiles/test_resources/ssl/java_client_truststore.jks"; + String TRUSTSTORE_PASSWORD = "password"; + + String BROKER_KEYSTORE = "test-profiles/test_resources/ssl/java_broker_keystore.jks"; + String BROKER_KEYSTORE_PASSWORD = "password"; +} diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.java new file mode 100644 index 0000000000..c651d3ec7f --- /dev/null +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.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.test.utils; + +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; + +public class TestUtils +{ + public static String dumpThreads() + { + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(true, true); + StringBuilder dump = new StringBuilder(); + dump.append(String.format("%n")); + for (ThreadInfo threadInfo : threadInfos) + { + dump.append(threadInfo); + } + + long[] deadLocks = threadMXBean.findDeadlockedThreads(); + if (deadLocks != null && deadLocks.length > 0) + { + ThreadInfo[] deadlockedThreads = threadMXBean.getThreadInfo(deadLocks); + dump.append(String.format("%n")); + dump.append("Deadlock is detected!"); + dump.append(String.format("%n")); + for (ThreadInfo threadInfo : deadlockedThreads) + { + dump.append(threadInfo); + } + } + return dump.toString(); + } +} diff --git a/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java b/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java index 2b99289cd1..d77731d09f 100644 --- a/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java +++ b/java/systests/src/main/java/org/apache/qpid/util/LogMonitor.java @@ -30,8 +30,10 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; +import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Map; /** * Utility to simplify the monitoring of Log4j file output @@ -42,6 +44,8 @@ import java.util.List; */ public class LogMonitor { + private static final Logger _logger = Logger.getLogger(LogMonitor.class); + // The file that the log statements will be written to. private final File _logfile; @@ -90,6 +94,8 @@ public class LogMonitor _appender.setImmediateFlush(true); Logger.getRootLogger().addAppender(_appender); } + + _logger.info("Created LogMonitor. Monitoring file: " + _logfile.getAbsolutePath()); } /** @@ -156,6 +162,39 @@ public class LogMonitor return results; } + public Map> findMatches(String... pattern) throws IOException + { + + Map> results= new HashMap>(); + for (String p : pattern) + { + results.put(p, new LinkedList()); + } + LineNumberReader reader = new LineNumberReader(new FileReader(_logfile)); + try + { + while (reader.ready()) + { + String line = reader.readLine(); + if (reader.getLineNumber() > _linesToSkip) + { + for (String p : pattern) + { + if (line.contains(p)) + { + results.get(p).add(line); + } + } + } + } + } + finally + { + reader.close(); + } + + return results; + } /** * Checks the log file for a given message to appear. If the caller * has previously called {@link #markDiscardPoint()}, lines up until the discard diff --git a/java/test-profiles/CPPExcludes b/java/test-profiles/CPPExcludes index 018ced4a68..8b74a19b8e 100755 --- a/java/test-profiles/CPPExcludes +++ b/java/test-profiles/CPPExcludes @@ -23,8 +23,6 @@ org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testCreateEx // QPID-3576: Java client issue. MessageConsumer#close() time-out. org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testDeleteOptions -org.apache.qpid.test.unit.client.channelclose.ChannelCloseTest#* - // Those tests are testing 0.8 specific semantics org.apache.qpid.test.client.ImmediateAndMandatoryPublishingTest#* @@ -128,17 +126,8 @@ org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#testFlowContro org.apache.qpid.test.client.RollbackOrderTest#testOrderingAfterRollbackOnMessage#* -//Excluded due to QPID-1447 : CPP broker does not have SlowConsumer Disconnection -org.apache.qpid.systest.GlobalQueuesTest#* -org.apache.qpid.systest.GlobalTopicsTest#* -org.apache.qpid.systest.MergeConfigurationTest#* -org.apache.qpid.systest.SubscriptionTest#* -org.apache.qpid.systest.TopicTest#* - // Excluded because Java plugins not used in CPP broker org.apache.qpid.server.virtualhost.plugin.* -org.apache.qpid.server.virtualhost.plugin.policies.* -org.apache.qpid.info.systest.InfoPluginTest#* org.apache.qpid.info.test.* org.apache.qpid.server.security.access.* org.apache.qpid.server.security.access.plugins.* @@ -182,4 +171,15 @@ org.apache.qpid.systest.disttest.* org.apache.qpid.disttest.* // Exclude java broker REST API tests -org.apache.qpid.server.management.plugin.servlet.rest.* +org.apache.qpid.systest.rest.* +org.apache.qpid.systest.rest.acl.* + +// Exclude failover tests requiring virtual host functionality +org.apache.qpid.client.failover.MultipleBrokersFailoverTest#* + +// Uses Java broker specific configuration +org.apache.qpid.client.ssl.SSLTest#testClientCertMissingWhilstWanting + +// QPID-2796 : Java 0-10 client only sends heartbeats in response to heartbeats from the server, not timeout based +org.apache.qpid.client.HeartbeatTest#testReadOnlyConnectionHeartbeats + diff --git a/java/test-profiles/Excludes b/java/test-profiles/Excludes index c0532e0b97..9c07fea574 100644 --- a/java/test-profiles/Excludes +++ b/java/test-profiles/Excludes @@ -30,4 +30,3 @@ org.apache.qpid.server.logging.MemoryMessageStoreLoggingTest#testMessageStoreClo org.apache.qpid.server.logging.DerbyMessageStoreLoggingTest#* org.apache.qpid.client.ssl.SSLTest#testVerifyLocalHostLocalDomain - diff --git a/java/test-profiles/Java010Excludes b/java/test-profiles/Java010Excludes index ca2383a8f3..c4b3ac8d66 100755 --- a/java/test-profiles/Java010Excludes +++ b/java/test-profiles/Java010Excludes @@ -37,9 +37,6 @@ org.apache.qpid.test.unit.close.JavaServerCloseRaceConditionTest#* //QPID-1864: rollback with subscriptions does not work in 0-10 yet org.apache.qpid.test.client.RollbackOrderTest#testOrderingAfterRollbackOnMessage -// This test uses 0-8 channel frames -org.apache.qpid.test.unit.client.channelclose.ChannelCloseTest#* - //QPID-3422: test fails because ring queue is not implemented on java broker org.apache.qpid.test.client.destination.AddressBasedDestinationTest#testBrowseMode @@ -64,3 +61,6 @@ org.apache.qpid.client.failover.AddressBasedFailoverBehaviourTest#testFlowContro // QPID-3604: Immediate Prefetch no longer supported by 0-10 org.apache.qpid.client.AsynchMessageListenerTest#testImmediatePrefetchWithMessageListener + +// QPID-2796 : Java 0-10 client only sends heartbeats in response to heartbeats from the server, not timeout based +org.apache.qpid.client.HeartbeatTest#testReadOnlyConnectionHeartbeats diff --git a/java/test-profiles/JavaTransientExcludes b/java/test-profiles/JavaTransientExcludes index e7b423ef34..2f96584589 100644 --- a/java/test-profiles/JavaTransientExcludes +++ b/java/test-profiles/JavaTransientExcludes @@ -20,6 +20,8 @@ //These tests require a persistent store org.apache.qpid.server.persistent.NoLocalAfterRecoveryTest#* org.apache.qpid.server.store.PersistentStoreTest#* +org.apache.qpid.server.logging.AlertingTest#testAlertingReallyWorksWithRestart +org.apache.qpid.server.logging.AlertingTest#testAlertingReallyWorksWithChanges org.apache.qpid.test.unit.ack.ClientAcknowledgeTest#testClientAckWithLargeFlusherPeriod org.apache.qpid.test.unit.ct.DurableSubscriberTest#* diff --git a/java/test-profiles/cpp.ssl.excludes b/java/test-profiles/cpp.ssl.excludes index 14c8ac2fe3..3d7b929831 100644 --- a/java/test-profiles/cpp.ssl.excludes +++ b/java/test-profiles/cpp.ssl.excludes @@ -17,8 +17,6 @@ // under the License. // -#org.apache.qpid.test.client.failover.FailoverTest#* - //This test does not supply a client keystore, therefore it cant login to the C++ broker //in this test profile as it demands client certificate authentication org.apache.qpid.client.ssl.SSLTest#testCreateSSLConnectionUsingConnectionURLParamsTrustStoreOnly diff --git a/java/test-profiles/java-bdb-spawn.0-10.testprofile b/java/test-profiles/java-bdb-spawn.0-10.testprofile index 35991645d8..78ab05a179 100644 --- a/java/test-profiles/java-bdb-spawn.0-10.testprofile +++ b/java/test-profiles/java-bdb-spawn.0-10.testprofile @@ -19,11 +19,11 @@ broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT -broker.config=build/etc/config-systests-bdb.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-bdb-spawn.0-8.testprofile b/java/test-profiles/java-bdb-spawn.0-8.testprofile index a4b74748e6..7f6efcbc3d 100644 --- a/java/test-profiles/java-bdb-spawn.0-8.testprofile +++ b/java/test-profiles/java-bdb-spawn.0-8.testprofile @@ -19,15 +19,15 @@ broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-bdb.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT broker.version=v0_8 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile b/java/test-profiles/java-bdb-spawn.0-9-1.testprofile index 9cd70a4ea7..28668b94f7 100644 --- a/java/test-profiles/java-bdb-spawn.0-9-1.testprofile +++ b/java/test-profiles/java-bdb-spawn.0-9-1.testprofile @@ -19,15 +19,15 @@ broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-bdb.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT broker.version=v0_9_1 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb-spawn.0-9.testprofile b/java/test-profiles/java-bdb-spawn.0-9.testprofile index 5c0ad2baf3..aa8e6830d4 100644 --- a/java/test-profiles/java-bdb-spawn.0-9.testprofile +++ b/java/test-profiles/java-bdb-spawn.0-9.testprofile @@ -19,15 +19,15 @@ broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-bdb.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT broker.version=v0_9 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb.0-10.testprofile b/java/test-profiles/java-bdb.0-10.testprofile index 892188aa24..8c4b145e0b 100644 --- a/java/test-profiles/java-bdb.0-10.testprofile +++ b/java/test-profiles/java-bdb.0-10.testprofile @@ -20,11 +20,11 @@ broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT -broker.config=build/etc/config-systests-bdb.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore profile.excludes=JavaExcludes JavaPersistentExcludes Java010Excludes JavaBDBExcludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-bdb.0-8.testprofile b/java/test-profiles/java-bdb.0-8.testprofile index 87eea96dda..acf031040e 100644 --- a/java/test-profiles/java-bdb.0-8.testprofile +++ b/java/test-profiles/java-bdb.0-8.testprofile @@ -20,15 +20,15 @@ broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-bdb.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT broker.version=v0_8 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb.0-9-1.testprofile b/java/test-profiles/java-bdb.0-9-1.testprofile index 1339dc1dc7..fa86720bbb 100644 --- a/java/test-profiles/java-bdb.0-9-1.testprofile +++ b/java/test-profiles/java-bdb.0-9-1.testprofile @@ -20,15 +20,15 @@ broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-bdb.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT broker.version=v0_9_1 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-bdb.0-9.testprofile b/java/test-profiles/java-bdb.0-9.testprofile index c097d53c85..ed3d7b2170 100644 --- a/java/test-profiles/java-bdb.0-9.testprofile +++ b/java/test-profiles/java-bdb.0-9.testprofile @@ -20,15 +20,15 @@ broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-bdb.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-bdb.xml messagestore.class.name=org.apache.qpid.server.store.berkeleydb.BDBMessageStore profile.excludes=JavaExcludes JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes broker.clean.between.tests=true broker.persistent=true -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT broker.version=v0_9 # # Do not enable. Allow client to attempt 0-10 and negotiate downwards diff --git a/java/test-profiles/java-dby-mem.0-10.testprofile b/java/test-profiles/java-dby-mem.0-10.testprofile index 33f9527c86..bfe031b338 100644 --- a/java/test-profiles/java-dby-mem.0-10.testprofile +++ b/java/test-profiles/java-dby-mem.0-10.testprofile @@ -20,12 +20,12 @@ broker.language=java broker.version=v0_10 broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT -broker.config=build/etc/config-systests-derby-mem.xml -messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml +messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes broker.clean.between.tests=true broker.persistent=true diff --git a/java/test-profiles/java-dby-mem.0-8.testprofile b/java/test-profiles/java-dby-mem.0-8.testprofile index 89bad84769..28bce8e434 100644 --- a/java/test-profiles/java-dby-mem.0-8.testprofile +++ b/java/test-profiles/java-dby-mem.0-8.testprofile @@ -20,12 +20,12 @@ broker.version=v0_8 broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-derby-mem.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT -messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml +messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true diff --git a/java/test-profiles/java-dby-mem.0-9-1.testprofile b/java/test-profiles/java-dby-mem.0-9-1.testprofile index 8deea281a4..0d2f82ebb5 100644 --- a/java/test-profiles/java-dby-mem.0-9-1.testprofile +++ b/java/test-profiles/java-dby-mem.0-9-1.testprofile @@ -20,12 +20,12 @@ broker.version=v0_9_1 broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-derby-mem.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT -messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml +messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true diff --git a/java/test-profiles/java-dby-mem.0-9.testprofile b/java/test-profiles/java-dby-mem.0-9.testprofile index b691a7d153..4dd9fbb899 100644 --- a/java/test-profiles/java-dby-mem.0-9.testprofile +++ b/java/test-profiles/java-dby-mem.0-9.testprofile @@ -20,12 +20,12 @@ broker.version=v0_9 broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-derby-mem.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT -messagestorefactory.class.name=org.apache.qpid.server.store.derby.DerbyMessageStoreFactory +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby-mem.xml +messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true broker.persistent=true diff --git a/java/test-profiles/java-dby-spawn.0-10.testprofile b/java/test-profiles/java-dby-spawn.0-10.testprofile index e2e2b44dae..9795533b52 100644 --- a/java/test-profiles/java-dby-spawn.0-10.testprofile +++ b/java/test-profiles/java-dby-spawn.0-10.testprofile @@ -19,11 +19,11 @@ broker.language=java broker.version=v0_10 broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT -broker.config=build/etc/config-systests-derby.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-dby-spawn.0-8.testprofile b/java/test-profiles/java-dby-spawn.0-8.testprofile index 3f609226e3..a980fd181d 100644 --- a/java/test-profiles/java-dby-spawn.0-8.testprofile +++ b/java/test-profiles/java-dby-spawn.0-8.testprofile @@ -19,11 +19,11 @@ broker.version=v0_8 broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-dby-spawn.0-9-1.testprofile b/java/test-profiles/java-dby-spawn.0-9-1.testprofile index 80d40458fd..04428b5021 100644 --- a/java/test-profiles/java-dby-spawn.0-9-1.testprofile +++ b/java/test-profiles/java-dby-spawn.0-9-1.testprofile @@ -19,11 +19,11 @@ broker.version=v0_9_1 broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-dby-spawn.0-9.testprofile b/java/test-profiles/java-dby-spawn.0-9.testprofile index 122eccdca1..4724eba660 100644 --- a/java/test-profiles/java-dby-spawn.0-9.testprofile +++ b/java/test-profiles/java-dby-spawn.0-9.testprofile @@ -19,11 +19,11 @@ broker.version=v0_9 broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-dby.0-10.testprofile b/java/test-profiles/java-dby.0-10.testprofile index d3b03054de..a2b1a41c31 100644 --- a/java/test-profiles/java-dby.0-10.testprofile +++ b/java/test-profiles/java-dby.0-10.testprofile @@ -20,11 +20,11 @@ broker.language=java broker.version=v0_10 broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT -broker.config=build/etc/config-systests-derby.xml +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes Java010Excludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-dby.0-8.testprofile b/java/test-profiles/java-dby.0-8.testprofile index 51580e6c7a..509796331f 100644 --- a/java/test-profiles/java-dby.0-8.testprofile +++ b/java/test-profiles/java-dby.0-8.testprofile @@ -20,11 +20,11 @@ broker.version=v0_8 broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-dby.0-9-1.testprofile b/java/test-profiles/java-dby.0-9-1.testprofile index b92397eae7..be087a6344 100644 --- a/java/test-profiles/java-dby.0-9-1.testprofile +++ b/java/test-profiles/java-dby.0-9-1.testprofile @@ -20,11 +20,11 @@ broker.version=v0_9_1 broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-dby.0-9.testprofile b/java/test-profiles/java-dby.0-9.testprofile index 17363b7e47..3b5e586ba4 100644 --- a/java/test-profiles/java-dby.0-9.testprofile +++ b/java/test-profiles/java-dby.0-9.testprofile @@ -20,11 +20,11 @@ broker.version=v0_9 broker.language=java broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.config=build/etc/config-systests-derby.xml -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests-derby.xml messagestore.class.name=org.apache.qpid.server.store.derby.DerbyMessageStore profile.excludes=JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes broker.clean.between.tests=true diff --git a/java/test-profiles/java-mms-spawn.0-10.testprofile b/java/test-profiles/java-mms-spawn.0-10.testprofile index 57af5c4a41..71aaf48562 100644 --- a/java/test-profiles/java-mms-spawn.0-10.testprofile +++ b/java/test-profiles/java-mms-spawn.0-10.testprofile @@ -19,10 +19,11 @@ broker.version=v0_10 broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests.xml # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # diff --git a/java/test-profiles/java-mms-spawn.0-8.testprofile b/java/test-profiles/java-mms-spawn.0-8.testprofile index 24f088e0c5..6365fa20f0 100644 --- a/java/test-profiles/java-mms-spawn.0-8.testprofile +++ b/java/test-profiles/java-mms-spawn.0-8.testprofile @@ -19,10 +19,11 @@ broker.version=v0_8 broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests.xml # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # diff --git a/java/test-profiles/java-mms-spawn.0-9-1.testprofile b/java/test-profiles/java-mms-spawn.0-9-1.testprofile index c1f6d10675..1eb4b00a1d 100644 --- a/java/test-profiles/java-mms-spawn.0-9-1.testprofile +++ b/java/test-profiles/java-mms-spawn.0-9-1.testprofile @@ -19,10 +19,11 @@ broker.version=v0_9_1 broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests.xml # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # diff --git a/java/test-profiles/java-mms-spawn.0-9.testprofile b/java/test-profiles/java-mms-spawn.0-9.testprofile index 421ae7476e..4ebce66c05 100644 --- a/java/test-profiles/java-mms-spawn.0-9.testprofile +++ b/java/test-profiles/java-mms-spawn.0-9.testprofile @@ -19,10 +19,11 @@ broker.version=v0_9 broker.language=java broker.type=spawned -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests.xml # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # diff --git a/java/test-profiles/java-mms.0-10.testprofile b/java/test-profiles/java-mms.0-10.testprofile index 6dd40cff47..0de5ffea09 100644 --- a/java/test-profiles/java-mms.0-10.testprofile +++ b/java/test-profiles/java-mms.0-10.testprofile @@ -20,9 +20,10 @@ broker.language=java broker.version=v0_10 broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-1-0 @PORT --exclude-1-0 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests.xml profile.excludes=JavaTransientExcludes Java010Excludes diff --git a/java/test-profiles/java-mms.0-8.testprofile b/java/test-profiles/java-mms.0-8.testprofile index f82bf8c473..dddad95157 100644 --- a/java/test-profiles/java-mms.0-8.testprofile +++ b/java/test-profiles/java-mms.0-8.testprofile @@ -20,10 +20,11 @@ broker.language=java broker.version=v0_8 broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT --exclude-0-9 @PORT --exclude-0-9 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1,AMQP_0_9 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests.xml # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # diff --git a/java/test-profiles/java-mms.0-9-1.testprofile b/java/test-profiles/java-mms.0-9-1.testprofile index 9b8baaa5a3..3c2f68a2c9 100644 --- a/java/test-profiles/java-mms.0-9-1.testprofile +++ b/java/test-profiles/java-mms.0-9-1.testprofile @@ -20,10 +20,11 @@ broker.language=java broker.version=v0_9_1 broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests.xml # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # diff --git a/java/test-profiles/java-mms.0-9.testprofile b/java/test-profiles/java-mms.0-9.testprofile index 56ace6d9e1..992168b044 100644 --- a/java/test-profiles/java-mms.0-9.testprofile +++ b/java/test-profiles/java-mms.0-9.testprofile @@ -20,10 +20,11 @@ broker.language=java broker.version=v0_9 broker.type=internal #broker.command only used for the second broker during failover tests in this profile -broker.command=build/bin/qpid-server -p @PORT -m @MPORT @EXCLUDES @INCLUDES -c @CONFIG_FILE -l @LOG_CONFIG_FILE +broker.command=build/bin/qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE broker.ready=BRK-1004 broker.stopped=Exception -broker.protocol.excludes=--exclude-0-10 @PORT --exclude-0-10 @SSL_PORT --exclude-1-0 @PORT --exclude-1-0 @SSL_PORT --exclude-0-9-1 @PORT --exclude-0-9-1 @SSL_PORT +qpid.broker_default_amqp_protocol_excludes=AMQP_1_0,AMQP_0_10,AMQP_0_9_1 +broker.virtualhosts-config=${QPID_HOME}/etc/virtualhosts-systests.xml # # Do not enable. Allow client to attempt 0-10 and negotiate downwards # diff --git a/java/test-profiles/testprofile.defaults b/java/test-profiles/testprofile.defaults index 47992b9334..033da12a97 100644 --- a/java/test-profiles/testprofile.defaults +++ b/java/test-profiles/testprofile.defaults @@ -20,7 +20,7 @@ java.naming.factory.initial=org.apache.qpid.jndi.PropertiesFileInitialContextFac java.naming.provider.url=${test.profiles}/test-provider.properties broker.ready=Listening on TCP -broker.config=build/etc/config-systests.xml +broker.config=build/etc/config-systests.json messagestore.class.name=org.apache.qpid.server.store.MemoryMessageStore broker.protocol.excludes= broker.persistent=false @@ -33,13 +33,20 @@ amqj.logging.level=${log} amqj.server.logging.level=${log} amqj.protocol.logging.level=${log} root.logging.level=warn -log4j.configuration=test-profiles/log4j-test.xml + +# System property log4j.configuration is used by log4j. +# QpidBrokerTestCase uses log4j.configuration.file to construct a java.io.File, eg for log configuration of spawned brokers. +log4j.configuration.file=${test.profiles}/log4j-test.xml +log4j.configuration=file:///${log4j.configuration.file} + log4j.debug=false # Note test-provider.properties also has variables of same name. # Keep in sync test.port=15672 test.mport=18999 +test.cport=19099 +test.hport=18080 #Note : Management will start open second port on: mport + 100 : 19099 test.port.ssl=15671 test.port.alt=25672 @@ -55,5 +62,7 @@ haltonerror=no exclude.modules=none profile.clustered=false +broker.config-store-type=json +broker.virtualhosts-config="${QPID_HOME}/etc/virtualhosts-systests.xml" -- cgit v1.2.1